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;
}
/*

*/
posted @ 2025-01-25 14:43  Rainbow_qwq  阅读(194)  评论(0)    收藏  举报