BZOJ4903 [Ctsc2017]吉夫特(洛谷P3773)

lucas DP

BZOJ题目传送门
洛谷题目传送门

这道题翰爷很早以前讲过,然而当时我连lucas都不会,今天又讲到这题才听懂。

要使那个式子模 2 > 0 ,则每一项都必须为 1 。由lucas定理得最终只有四种情况: C 0 0 , C 1 0 , C 0 1 , C 1 1 。可以发现只有 C 0 1 这一个为0, C n m   m o d   2 其实是每一位分别计算后的乘积。那么要使式子不为0,就说明 a b i a b i 1 的子集,即 a b i &   a b i 1 = a b i

f [ i ] 表示以 i 结尾的满足条件的不上升子序列个数。那么我们每读入一个 x 就去找子集为 x 的数累加即可。

代码:

#include<cctype>
#include<cstdio>
#define F inline
#define N 233333
using namespace std;
const int p=1e9+7;
int n,ans,f[N+5];
F char readc(){
    static char buf[100000],*l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    return l==r?EOF:*l++;
}
F int _read(){
    int x=0; char ch=readc();
    while (!isdigit(ch)) ch=readc();
    while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
    return x;
}
int main(){
    for (n=_read();n;n--){
        int x=_read();
        for (int i=x;i<=N;i=i+1|x)
            f[x]=(f[x]+f[i])%p;
        ans=(ans+(f[x]++))%p;
    }
    return printf("%d\n",ans),0;
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/81045007