洛谷P3773 CTSC2017 吉夫特

对于组合数的奇偶性:

根据卢卡斯定理,相当于是在p进制下的分解,对于每一C(n,m),如果n,m不同,那组合数就是偶数

所以组合数C(n,m)为奇数当且仅当 n&m==m

然后就是dp了

设f[i]为以i结尾的方案数

枚举i的子集j,如果j的位置在i的后面且i&j==j,则更新

答案就是所有f[a[i]]的和

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;
typedef long long ll;

const int maxn = 255555;
const int mod = 1e9+7;

int n,m,up,ans;
int a[maxn],c[maxn];
int f[maxn]; // 以i为结尾 

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}

int main(){
    n=read();
    for(int i=1;i<=n;++i) a[i]=read(),c[a[i]]=i,up=max(up,a[i]),f[a[i]]=1;
    
    for(int i=1;i<=n;++i){
        for(int j=(a[i]-1)&a[i];j;j=(j-1)&a[i]){ // 枚举子集 
            if(c[j]>i){
                if((a[i]&j)==j) f[j]=(f[j]+f[a[i]])%mod;
            }
        }
    }
    for(int i=1;i<=n;i++){
        ans=(ans+f[a[i]]-1)%mod;
    }
    printf("%d\n",ans);
    
    return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/10415486.html