题目描述:
给出 个互不相同的数 ,求一个长为 的序列 ,满足 的方案数模2的值。
题目分析:
设每个 出现了 次,那么 ,考虑对应到排列上,那么序列 对方案数的贡献次数是
那么一个序列 的贡献模2余1,则要求上面的式子不能被2整除,我们知道式子中含2的因子数
而 ,与库默尔定理类似,这意味着在二进制下做加法不能进位。即 是 二进制下的子集
那么考虑 每一位 1 分配给哪个 ,即求
的序列 的方案数模 2
从低位往高位类数位DP,每次可以确定最低位,设状态 为已经确定了前 位,当前的和为 的方案数,那么转移就是加入一个 。然后根据 在当前位的值确定保留哪些方案,然后整体除以2。和最大为
复杂度 ,bitset优化至
Code:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int T,K,A[205],Mx;
LL N,S;
bitset<200005>f,g;
int main()
{
for(scanf("%d",&T);T--;){
scanf("%lld%lld%d",&N,&S,&K),Mx=0;
for(int i=1;i<=K;i++) scanf("%d",&A[i]),Mx=max(Mx,A[i]);
f.reset(),f[0]=1;
for(int i=0;N;N>>=1,S>>=1,i++){
if(N&1){
g.reset();
for(int j=1;j<=K;j++) g^=f<<A[j];
}
else g=f;
f.reset();
for(int j=S&1;j<=2*Mx;j+=2) f[j>>1]=g[j];
}
printf("%d\n",int(f[S]));
}
}