版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/85911285
思路分析:
设, 当且仅当按开关j开关i的状态改变时, 否则, 如果按开关i则
, 否则, 为开关的初始状态, 为开关i的目标状态, XOR表示异或运算, 可得如下方程组:
....
如果上述方程组无解, 则方案数为0, 如果有唯一解则方案数为1, 如果自由元个数为k()个, 则方案数为个(因为只能为0或1)
具体实现见如下AC代码:
//POJ1830_开关问题
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 100;
int N, a[MAX];//a[i]:增广矩阵第i行
int main(){
int K; scanf("%d", &K);
while(K--){
scanf("%d", &N);
memset(a, 0, sizeof(a));
for(int i = 1; i <= N; ++i) scanf("%d", &a[i]);
for(int i = 1; i <= N; ++i){
int y; scanf("%d", &y), a[i] ^= y;
a[i] |= 1 << i;//a[i][i]为1
}
int u, v;
while(scanf("%d %d", &u, &v), u && v) a[v] |= 1 << u;
int res = 1;
//开始高斯消元
for(int i = 1; i <= N; ++i){
for(int j = i; j <= N; ++j) if(a[i] < a[j]) swap(a[i], a[j]);
if(!a[i]){
res = 1 << N - i + 1; break;
}
if(a[i] == 1){
res = 0; break;
}
//查找a[i]最高位的1, 然后消元
for(int j = N; j >= 1; --j)
if(a[i] >> j & 1){
for(int k = 1; k <= N; ++k){
if(i == k) continue;
if(a[k] >> j & 1) a[k] ^= a[i];
}
break;
}
}
if(!res) cout << "Oh,it's impossible~!!" << endl;
else cout << res << endl;
}
return 0;
}
扫描二维码关注公众号,回复:
4797670 查看本文章