代码的大部分都是和poj1222一样的,求出自由变元个数就好了。
1222题解:http://blog.csdn.net/moringrain/article/details/47397787
这道题需要学习的地方是如何处理初始状态和目标状态。
初始状态-->目标状态 等同于 全0状态-->初始状态 xor 目标状态
另外给系数赋值的时候注意行列的顺序,一开始搞错了调了半天(样例很弱,一开始错了也能过)
总之,这类题在给系数赋值的时候一定要多过脑子。
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 50; //未知数数目
int equ, var; //equ个方程,var个变元
int a[MAXN][MAXN]; //行数为equ,0~var列为系数,var列为得数
int x[MAXN]; //解集
int free_num; //自由变元数量
int free_x[MAXN]; //自由变元,多解枚举时会用到
/*******************************************************
* mod2高斯消元过程
* 返回-1无解,0惟一解,>0自由变元数目
*******************************************************/
int Gauss()
{
int maxr, col, i, j, k;
free_num = 0;
for (k = 0, col = 0; k<equ && col<var; k++, col++)
{
maxr = k;
for (i = k + 1; i<equ; i++)
{
if (abs(a[i][col])>abs(a[maxr][col]))
maxr = i;
}
if (a[maxr][col] == 0)
{
k--;
free_x[free_num++] = col; //出现一个自由变元
continue;
}
if (maxr != k)
{
for (j = col; j<var + 1; j++)
swap(a[k][j], a[maxr][j]);
}
for (i = k + 1; i<equ; i++)
{
if (a[i][col] != 0)
{
for (j = col; j<var + 1; j++)
a[i][j] ^= a[k][j];
}
}
}
for (i = k; i<equ; i++)
if (a[i][col] != 0)
return -1; //无解情况
if (k<var)
return var - k; //多个自由变元
for (i = var - 1; i >= 0; i--) //惟一解,进行回代
{
x[i] = a[i][var];
for (j = i + 1; j<var; j++)
x[i] ^= (a[i][j] && x[j]);
}
return 0;
}
void work()
{
int i, j, n, k, t, ans;
int inital_sate[MAXN], target_state[MAXN];
memset(a, 0, sizeof(a));
memset(x, 0, sizeof(x));
scanf("%d",&n);
equ = var = n;
for (i = 0; i < n; i++)
scanf("%d", &inital_sate[i]);
for (i = 0; i < n; i++)
scanf("%d", &target_state[i]);
for (i = 0; i < n; i++)
{
a[i][i] = 1;
a[i][n] = inital_sate[i] ^ target_state[i];
}
while (scanf("%d%d", &k, &t) == 2)
{
if (k == 0 && t == 0) break;
a[t - 1][k - 1] = 1; //注意kt别写反了
}
ans = Gauss();
if (ans == -1)
printf("Oh,it's impossible~!!\n");
else
printf("%d\n",(1<<ans));
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
work();
return 0;
}