1. CZday3C

给定有m个数的集合,从其中任选一个子集满足全部&后不为零,问方案数。

考虑对二进制位容斥,问题转化为求包含某个二进制位集合的数的个数,通过类似FMT的DP求解。

 1 #include<bits/stdc++.h>
 2 #define mo 1000000007
 3 #define ll long long
 4 using namespace std;
 5 ll m,n,k,f[1100010],g[1100010],x,ans;
 6 ll po(ll x,ll y){ll z=1;while (y){if (y%2==1)z=(x*z)%mo;x=(x*x)%mo;y/=2;}return z;}
 7 int main(){
 8     freopen("loneliness.in","r",stdin);
 9     freopen("loneliness.out","w",stdout);
10     cin>>n;
11     cin>>n>>m>>k;
12     for (int i=1;i<=m;i++){scanf("%d",&x);g[x]++;}
13     f[0]=-1;
14     for (int i=0;i<(1<<n);i++)
15         for (int j=1;j<(1<<n);j*=2)
16             if ((i&j)==0)f[i+j]=f[i]*(-1);
17     for (int i=1;i<(1<<n);i*=2)
18         for (int j=0;j<(1<<n);j++)
19             if ((i&j)!=0) g[j-i]+=g[j];
20     for (int i=1;i<(1<<n);i++)ans=(ans+f[i]*po(g[i],k)+mo)%mo;
21     cout<<ans<<endl;
22     return 0;
23 }
View Code

相关文章: