ABC366 G - XOR Neighbors 题解

发现题目实质上就是让你构造一组 a1,2,,n,有一些限制,要求一些 a 异或起来是 0

看到 n60,果断列异或方程组,用异或高斯消元。

具体地,有 n 个方程组,ai,j 表示第 i 个方程中 j 的系数。对于每一个变量 i,要把 j>i 的方程中的第 i 项用第 i 个方程异或起来消掉(如果 ai,i=0 就把一个 aj,i0j>i 的方程和第 i 个方程交换),因为等号右边是 0 所以可以不用处理。

从后往前构造解,如果 ai,i=0,这是可能的,那么就令 ansi=2i1;否则,就令 ansi=j>iansj×ai,j

后一点比较容易理解,前一点不太容易理解,我认为这样子填 ansi 的话对于 j<iansj 的第 i 位反映的是 ansiansj 是否有影响,如果 ansj=0ansj 的第 i 位一定是 0,这样子 ansiansj 没有影响,这样子 ansj0 这件事就和 ansi 无关的。类似的,可以发现这和每一个填 ansi=2i1ansi 都没有关系,那么只能说明 ansj=0 是命中注定的,该局面无解。

事实上有人在 ai,i=0 时填 rand 也过了。

如果存在一个 ansi=0,那么一定无解。

点击开 D
const int N=65;
int n,m,a[N][N]={};
ll ans[N]={};
int main()
{
//	usefile("G");
	int i,j,k,x,y;
	read(n,m);
	for(i=1;i<=m;++i)
		read(x,y),a[x][y]^=1,a[y][x]^=1;
	for(i=1;i<=n;++i) {
		if(!a[i][i]) {
			for(j=i+1;j<=n;++j)
				if(a[j][i]) {
					swap(a[i],a[j]);
					break;
				}
		}
		if(!a[i][i]) continue;
		for(j=i+1;j<=n;++j)
			if(a[j][i]) {
				for(k=1;k<=n;++k)
					a[j][k]^=a[i][k];
			}
	}
	for(i=n;i;--i) {
		if(!a[i][i]) {
			ans[i]=(1ll<<i)-1;
			continue;
		}
		ans[i]=0;
		for(j=i+1;j<=n;++j)
			if(a[i][j])
				ans[i]^=ans[j];
	}
	for(i=1;i<=n;++i)
		if(!ans[i]) {
			printf("No\n");
			return 0;
		}
	printf("Yes\n");
	for(i=1;i<=n;++i)
		printf("%lld ",ans[i]);
	printf("\n");
	return 0;
}
posted @   fydj  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示