『高斯消元』开关问题(特殊解的判定+异或高消)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ronaldo7_ZYB/article/details/89816875

题目描述

有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。

你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。

对于任意一个开关,最多只能进行一次开关操作。

你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)

题解

我们设 a i , j a_{i,j} 表示第 j j 个开关变动的时候第 i i 个开关是否变动, 0 0 表示不变。

s t i st_i 表示起始状态, e d i ed_i 表示终止状态。则有一下异或方程:
a i , 1   x o r   a i , 2   x o r   . . .   x o r   a i , n   =   s t i   x o r   e d i , i [ 1 , n ] a_{i,1}\ xor\ a_{i,2}\ xor\ ...\ xor\ a_{i,n}\ =\ st_i\ xor\ ed_i,i∈[1,n]

显然异或是不进位的加法,我们可以直接进行异或高消。

现在考虑如何进行方案数的计算:显然在高斯消元的时候,假如在消第i列时,如果此时这一位后面的每一个数都是 0 0 的话,无论这些数的取值多少都是不必要的。若这一位之后又 k k 个数都为 0 0 ,则当前对答案的贡献就是 2 k 2^k 。若出现0=1的情况,则答案无解。

注意:在枚举每一列时只能统计一个数的方案;因为其他的某些数字可能由 0 0 变为非 0 0 数。

其实我们在这里总结一下:在每一次高斯消元的过程中,若出现系数全为 0 0 ,常数不为 0 0 的情况,则方程无解;若出现系数和常数都为 0 0 的情况,则有多组解。

代码如下:

#include <bits/stdc++.h>

using namespace std;

int n;
int a[100];

void init(void)
{
	cin>>n;
	for (int i=1,k;i<=n;++i) 
	{
		cin>>k;
		a[i] ^= k;
		a[i] |= (1<<i);//a[i][i] = 1
	}	
	for (int i=1,k;i<=n;++i)
	{
		cin>>k;
		a[i] ^= k;
	}
	int x,y;
	while (cin>>x>>y)
    {
    	if (!x && !y) break;
    	a[y] |= (1<<x);//a[y][x] = 1
    }
    return;
}

int work(void)
{
    init();
    for (int i=1;i<=n;++i)
    {
    	for (int j=i+1;j<=n;++j) 
    	    if (a[j]>a[i]) swap(a[i],a[j]);
    	if (a[i] == 1) return 0;//0 = 1,无解 
    	if (a[i] == 0) return 1<<(n-i+1);//确定i-1个解 
    	for (int k=n;k>=1;--k)//查找最高位的1的位置 
		{
    	    if ((a[i]>>k)&1 == 1) 
    	    {
    	    	for (int j=1;j<=n;++j)
    	        	if (i^j && (a[j]>>k)&1 == 1)//如果当前位=1则需要消元 
    	            	a[j] ^= a[i];
    	        break;
    	    }
    	}
    }
    return 1;
}

int main(void)
{
	freopen("switch.in","r",stdin);
	freopen("switch.out","w",stdout);
	int T;
	cin>>T;
	while (T --) 
	{
		memset(a,0,sizeof(a));
		int ans = work();
		if (ans == 0) cout<<"Oh,it's impossible~!!\n";
		else cout<<ans<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Ronaldo7_ZYB/article/details/89816875