题意:F(x) = (1+x)^a1 + (1+x)^a2 + ... + (1+x)^am,求系数是奇数的项的个数。
容斥原理:递归形式
dfs(int beg,set S,int sym)
{
ans+=num(S)*sym;
for(int i=beg;i<=n;i++)
dfs(i,S∩A[i],sym*-1);
}
for(int i=1;i<=n;i++)
dfs(i,A[i],1);
每个系数是一个集合,它的奇数次项的个数就是集合的个数,算法是2^(系数的二进制里1的个数).
两个集合的交是: 比如系数w1,w2,集合的交的个数是2^(w1&w2的二进制里1的个数)
由于奇数次幂相交不一定是奇数次幂,,所以所以要把偶数个集合的交的个数减掉,写一下式子,发现问题没有变复杂,只需把上面的递归式的sym由-1变为-2既可.
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
const int N=20;
LL w[N];
LL ans,n;
LL get(LL x)
{
return x==0? 0:get(x-(x&-x))+1;
}
void dfs(LL beg,LL num,LL sym)
{
ans+=((LL)1<<get(num))*sym;
for(LL i=beg+1;i<=n;i++)
dfs(i,num&w[i],-2*sym);
}
int main()
{
LL k=1,t,i;
cin>>t;
while(t--)
{
cin>>n;
for(i=1;i<=n;i++)
cin>>w[i];
ans=0;
for(i=1;i<=n;i++)
dfs(i,w[i],1);
cout<<"Case #"<<k++<<": "<<ans<<endl;
}
return 0;
}