PA 2016 5A pok 覆盖 mod 2
pok
钦定两个点等价 -> 它们到其他点的边相同
钦定 \(2^k\) 个点等价 -> 分成两个 \(2^{k-1}\),它们的内部边相同,它们之间的边相同
钦定 \(2^k\) 个点等价 -> 答案为奇数的集合是 \(2^k-2^m\) 其中 \(\binom mk \bmod 2 = 1\)
下面的做法里,让第二维取反,即状态记录的是不选的个数。
一个“集合划分方案”为 划分成若干个 \(2^k\),\(k\) 两两不同,每两组之间的边相同
如果一种划分方案下出现两个 k 相同,则钦定它们等价,然后钦定它们之间有没有边,递归成 k/k+1
DP 求出 n 个点的所有“集合划分方案” O(n^2)
对于一个“集合划分方案” \(2^{a_1}+2^{a_2}+..+2^{a_n}\),从高往低依次枚举贪心,
发现只可能生成 \(S\) 与 \(S-2^{a_1}\),其余 mod 2=0
int res[233];
void dfs(int n,int s,int now){
if(n==-1){
res[now]^=1;
return;
}
if((s>>n&1)){
if((1<<n)%2==0)dfs(n-1,s,now-(1<<n));
}else{
For(i,0,(1<<n)-1){
dfs(n-1,s|i,now);
}
}
}
#define maxn 16388
#define inf 0x3f3f3f3f
int n,k;
bitset<maxn> f[maxn],res[maxn];
void prew(int n){
f[1][1]=1;
For(i,2,n){
For(j,1,i-1){
if(f[i-1][j]){
res[i-1].flip(j);
res[i-1].flip(j^(j&-j));
int x=j,now=1;
while(1){
f[i].flip(x|now);
if(!(x&now))break;
x-=now,now<<=1;
}
}
}
}
}
signed main()
{
prew(1<<14|1);
int Q=read();
while(Q--){
int n=read(),k=read();
cout<<res[n][n-k]<<"\n";
}
return 0;
}
/*
*/