其他分享
首页 > 其他分享> > [CTSC2017]吉夫特

[CTSC2017]吉夫特

作者:互联网

Description

给出长为 \(n\) 的数列 \(\{a_n\}\),选出一个长度大于二的子序列,使得

\[\prod_{i=2}^K \binom{b_{i-1}}{b_i} \bmod 2=1 \]

求方案数。

Solution

对组合数取模,容易想到卢卡斯定理,条件就转化为在二进制下,\(b_{i-1}\) 的每一位都要大于等于 \(b_{i}\),那么利用集合思想,就能推出 \(b_{i-1}\&b_i=b_i\)。也就是说,满足这个条件就能在 \(b_{i-1}\) 后面接上一个 \(b_i\)。容易想到状态 \(dp_{i}\) 表示以 \(a_i\) 结尾的序列个数。转移显然。

\[dp_{i}=\sum_{a_{j}\&a_{i}=a_i\\ \quad j<i} dp_{j}+1 \]

那就能得到一个 \(O(n^2)\) 的 dp,期望得分 70。

再次观察,发现这题的值域很特殊,最大不过二十万。这就提示我们二进制分解下最多有 17 位。题目保证了 \(a_i\) 不同,那么一个 \(a_i\) 就唯一对应一个 \(i\),所以可以直接枚举 \(a_i\) 补集的子集再或上 \(a_i\),来枚举 \(a_j\) ,在判断一下 \(j\) 是不是在 \(i\) 前面即可。

因为 \(a_i\) 不同,所以最坏复杂度就是

\[\sum_{i=0}^{\log a_i} \binom{\log a_i}{i} 2^i=(2+1)^{\log a_i}=3^{\log a_i} \]

即 \(O(3^{\log a_i})\)

#include<stdio.h>
#define Mod 1000000007
#define N 240007

inline int read(){
    int x=0,flag=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

int n,a[N],dp[N],pos[N];
int main(){
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read(),pos[a[i]]=i;
    for(int i=n-1;i;i--){
        for(int j=a[i]&(a[i]-1);j;j=(j-1)&a[i])
            if(pos[j]>i) dp[i]=(dp[i]+dp[pos[j]]+1)%Mod;
    }
    int ans=0;
    for(int i=1;i<=n;i++) ans=(ans+dp[i])%Mod;
    printf("%d",ans);
}

标签:log,int,sum,夫特,getchar,CTSC2017,dp,Mod
来源: https://www.cnblogs.com/wwlwQWQ/p/14639500.html