3364 Lanterns (異或方程組高斯消元)

基本思路。首先構造一個n*(m+1)的矩陣,同時標記一個行數row,row從零開始,然後找出每一列第一個非零的數,和第row行互換,

然後對row到n行,異或運算。最終的結果爲2^(m-row)

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int array[55][55],n,m,h[55][55];
int main()
{
	int i,j,k,t,a,q;
	scanf("%d",&t);
	for(int v=1;v<=t;v++)
	{
		memset(array,0,sizeof(array));
		memset(h,0,sizeof(h));
		scanf("%d%d",&n,&m);
		for(i=0;i<m;i++)
		{
			scanf("%d",&k);
			while(k--)
			{
				scanf("%d",&a);
				array[a-1][i]=1;
			}
		}
		for(i=0;i<n;i++)
		for(j=0;j<m;j++)
			h[i][j]=array[i][j];
		printf("Case %d:\n",v);
		scanf("%d",&q);
		while(q--)
		{
			for(i=0;i<n;i++)
			for(j=0;j<m;j++)
				array[i][j]=h[i][j];
			for(i=0;i<n;i++)
				scanf("%d",&array[i][m]);
			/*for(i=0;i<n;i++)
			{
				for(j=0;j<=m;j++)
					printf("%d ",array[i][j]);
				printf("\n");
			}*/
			__int64 ans=1;
			int row=0;
			for(i=0;i<m;i++)
			{
				for(j=row;j<n;j++)
					if(array[j][i])
						break;
				if(j==n)continue;
				if(j!=row)
				{
					for(k=0;k<=m;k++)
						swap(array[row][k],array[j][k]);
				}
				for(j=row+1;j<n;j++)
				{
					if(array[j][i])
					{
						for(k=0;k<=m;k++)
							array[j][k]^=array[row][k];
					}
				}
				row++;//這裏不用擔心row超過n,因爲從n行開始,每行的數字都是0
			}
				for(j=row;j<n;j++)
					if(array[j][m])
					{
						ans=0;
						break;
					}
				int tmp=m-row;
				while(tmp--)
					ans*=2;
			printf("%I64d\n",ans);
		}
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章