开关问题
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 5106 | Accepted: 1876 |
Description
有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)
Input
输入第一行有一个数K,表示以下有K组测试数据。
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。
Output
如果有可行方法,输出总数,否则输出“Oh,it's impossible~!!” 不包括引号
Sample Input
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
4 Oh,it's impossible~!!
Hint
第一组数据的说明:
一共以下四种方法:
操作开关1
操作开关2
操作开关3
操作开关1、2、3 (不记顺序)
一共以下四种方法:
操作开关1
操作开关2
操作开关3
操作开关1、2、3 (不记顺序)
Source
开关问题,也是用高斯消元法求解。设消元后有r个非0行,且不存在矛盾方程(若存在,则无解),则一共有r个非自由变量,那么自由变量就有n-r个,因为每个自由变量都要0或1两种取值,那么解的个数就是1<<(n - r)。
AC代码:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
#include <ctime>
#include <vector>
#include <algorithm>
#define ll long long
#define L(rt) (rt<<1)
#define R(rt) (rt<<1|1)
using namespace std;
const int INF = 2000000000;
const int maxn = 35;
int a[maxn][maxn];
int n;
void gauss(){
int row = 0, col = 0;
while(row < n && col < n)
{
int id = row;
for(int i = row + 1; i < n; i++)
if(abs(a[i][col]) > abs(a[id][col]))
id = i;
if(a[id][col])
{
for(int i = col; i <= n; i++)
swap(a[id][i], a[row][i]);
for(int i = row + 1; i < n; i++)
if(a[i][col])
{
for(int j = col; j <= n; j++)
a[i][j] ^= a[row][j];
}
row++;
}
col++;
}
for(int i = row; i < n; i++)
if(a[i][n])
{
cout<<"Oh,it's impossible~!!"<<endl;
return;
}
printf("%d\n", 1 << (n - row));
}
int main()
{
int t, x, y;
scanf("%d", &t);
while(t--)
{
memset(a, 0, sizeof(a));
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d", &a[i][n]);
for(int i = 0; i < n; i++)
{
scanf("%d", &x);
a[i][n] ^= x;
a[i][i] = 1;
}
while(scanf("%d%d", &x, &y), x || y)
{
x--;
y--;
a[y][x] = 1;
}
gauss();
}
return 0;
}