Processing math: 100%

『开关问题 异或高消』

Parsnip·2019-04-16 14:31·284 次阅读

『开关问题 异或高消』

<更新提示>

<第一次更新>


<正文>

开关问题(POJ 1830)#

Description#

有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。

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

Input Format#

输入第一行有一个数K,表示以下有K组测试数据。 每组测试数据的格式如下: 第一行 一个数N(0 < N < 29) 第二行 N个0或者1的数,表示开始时N个开关状态。 第三行 N个0或者1的数,表示操作结束后N个开关的状态。 接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。

Output Format#

如果有可行方法,输出总数,否则输出“Oh,it's impossible~!!” 不包括引号

Sample Input#

Copy
2 3 0 0 0 1 1 1 1 2 1 3 2 1 2 3 3 1 3 2 0 0 3 0 0 0 1 0 1 1 2 2 1 0 0

Sample Output#

Copy
4 Oh,it's impossible~!!

解析#

xi代表是否操作了第i个开关,按了为1,不按为0fij代表开关i和开关j的联系情况,按下j会影响ifij=1,反之fij=0,对于任意的i,令fii=1

如果将第i个开关最后是否变化记为pi的话,就可以得到异或方程组:

{f11x1 xor f12x2 xor ... xor f1nxn=p1f21x1 xor f22x2 xor ... xor f2nxn=p2                                  ...fn1x1 xor fn2x2 xor ... xor fnnxn=pn

同样地,这个方程组也是可以高斯消元的,只需将加减操作改为异或即可。

对于本题,求的是方案数,那么我们分高斯消元的三种情况处理即可。当方程组恰好有解时,方案数为1,当方程组无解时,方案数为0,当方程组无穷解时,记录下自由元的个数p,由于每个x可以取10,所以方案数为2p

由于本题增广矩阵中所有元素非10,所以可以状态压缩一下,方便运算。

Code:

Copy
#include <bits/stdc++.h> using namespace std; const int N=30; int n,f[N],ans,t; inline void input(void) { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&f[i]); int x,y; for (int i=1;i<=n;i++) { scanf("%d",&x); f[i] ^= x; } while ( scanf("%d%d",&x,&y) && x && y ) f[y] |= 1 << x; } inline void init(void) { for (int i=1;i<=n;i++) f[i] |= 1 << i; } inline void Gauss(void) { ans = 1; for (int i=1;i<=n;i++) { for (int j=i+1;j<=n;j++) if ( f[j] > f[i] ) swap(f[j],f[i]); if (!f[i]){ans = 1 << (n-i+1);break;} if (f[i]==1){ans = 0;break;} for (int j=n;j>=1;j--) { if (f[i] >> j & 1) { for (int k=1;k<=n;k++) if ( i ^ k && ( f[k] >> j & 1 ) ) f[k] ^= f[i]; break; } } } } int main(void) { freopen("switch.in","r",stdin); freopen("switch.out","w",stdout); scanf("%d",&t); while (t--) { input(); init(); Gauss(); if ( !ans )printf("Oh,it's impossible~!!\n"); else printf("%d\n",ans); } return 0; }

<后记>

posted @   Parsnip  阅读(284)  评论(0)    收藏  举报
点击右上角即可分享
微信分享提示
目录