根本没想到可以用高斯消元来做,看了网上大牛的日志才知道,哎!自愧不如!下面正式讲解:

  首先一个开关最多只能又一次操作(或者没有操作),则对N个开关的操作可以用一个N维的向量来表示<x1,x2,....,xn>(1>=xi>=0),

用Aij表示对第j个开关操作,i开关会改变状态。Ei,Si分别表示开始时和最终时第i个开关的状态,则可以用如下的数学表达式表示:

E1^S1=(x1*A11)^...^(xn*A1n)

....

En^Sn=(x1*An1)^...^(xn*Ann)

将上述方程组表示成矩阵形式:

E1^S1          A11   A12  .....      A1n                 x1

...           =   ...........                             ^        ....

En^Sn          An1  An2  ....        Ann                 xn

下面就是用高斯消元对系数行列式消元!若最后又r行全是0那么有2^r种情况,因为有r个自由变量,意思是有r个开关可以操作也可以不操作,

但是其他的n-r个开关的是否操作是一定的。具体代码如下:

 

#include<iostream>
#include<vector>
using namespace std;
#define L 38
int a[L][L],s[L],t[L];
int gauss(int n)
{
	int ans=0,i=0,j=0,k=0,r=0;
	for(i=1,j=1;i<=n && j<=n;j++)
	{
		k=i;                          //当前消元到第i行
		while(k<=n && !a[k][j]) k++;  //直到找到第j列的第一个是1的元素所在的行k
		if(a[k][j])                   //此处包含k>n的情况
		{
			for(r=1;r<=n+1;r++)       //将第k行换到当前消元的行i
				swap(a[i][r],a[k][r]);
			for(r=1;r<=n;r++)         //如果当前行的第j列为1,除了第i行外的其他n-1行进行消元
			{
				if(r!=i && a[r][j])
				{
					for(k=i;k<=n+1;k++)
						a[r][k]=a[r][k]^a[i][k];
				}
			}
			i++;                      //成功消元第i行,消元下面的行
		}
	}
	for(j=i;j<=n;j++)                 //从第i行开始,如果有增广列不为0,则无解
	{
		if(a[j][n+1]) 
			return -1;
	}

	return 1<<(n-i+1);                //共有2^(n-i+1)种解
}
int main()
{
	int k,n,i=0,j=0,x,y;
	cin>>k;
	while(k--)
	{
		memset(a,0,sizeof(a));
		cin>>n;
		for(i=1;i<=n;i++)
			cin>>s[i];
		for(i=1;i<=n;i++)
		{
			cin>>t[i];
			a[i][i]=1;
			a[i][n+1]=s[i]^t[i];
		}
		while(true)
		{
			cin>>x>>y;
			if((x+y)==0) break;
			a[y][x]=1;            //注意此处一定是a[y][x]
		}
		int ans=gauss(n);
		if(ans==-1)
			cout<<"Oh,it's impossible~!!"<<endl;
		else
			cout<<ans<<endl;
	}
	return 1;
}

 

posted on 2013-05-21 22:17  一路狂奔的人  阅读(1125)  评论(0编辑  收藏  举报