poj1830(高斯消元解mod2方程组)
题目链接:http://poj.org/problem?id=1830
题意:中文题诶~
思路:高斯消元解 mod2 方程组
有 n 个变元,根据给出的条件列 n 个方程组,初始状态和终止状态不同的位置对应的方程右边常数项为1,状态相同的位置对于的方程组右边的常数项为0.然后用高斯消元解一下即可.若有唯一解输出1即可,要是存在 k 个变元,则答案为 1 << k, 因为每个变元都有01两种选择嘛~
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <string.h> 5 using namespace std; 6 7 const int inf = 1e9; 8 const int MAXN = 3e2; 9 int equ, var;//有equ个方程,var个变元,增广矩正行数为equ,列数为var+1,从0开始计数 10 int a[MAXN][MAXN];//增广矩正 11 int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用) 12 int free_num;//自由变元个数 13 int x[MAXN];//解集 14 15 int Gauss(void){//返回-1表示无解,0表示有唯一解,否则返回自由变元个数 16 int max_r, col, k; 17 free_num = 0; 18 for(k = 0, col = 0; k < equ && col < var; k++, col++){ 19 max_r = k; 20 for(int i = k + 1; i < equ; i++){ 21 if(abs(a[i][col] > abs(a[max_r][col]))) max_r = i; 22 } 23 if(a[max_r][col] == 0){ 24 k--; 25 free_x[free_num++] = col;//这个是变元 26 continue; 27 } 28 if(max_r != k){ 29 for(int j = col; j < var + 1; j++){ 30 swap(a[k][j], a[max_r][j]); 31 } 32 } 33 for(int i = k + 1; i < equ; i++){ 34 if(a[i][col] != 0){ 35 for(int j = col; j < var + 1; j++){ 36 a[i][j] ^= a[k][j]; 37 } 38 } 39 } 40 } 41 for(int i = k; i < equ; i++){ 42 if(a[i][col] != 0) return -1;//无解 43 } 44 if(k < var) return var - k;//返回自由变元个数 45 for(int i = var - 1; i >= 0; i--){ 46 x[i] = a[i][var]; 47 for(int j = i + 1; j < var; j++){ 48 x[i] ^= (a[i][j] && x[j]); 49 } 50 } 51 return 0; 52 } 53 54 void solve(void){ 55 int op = Gauss(); 56 if(op == -1) cout << "Oh,it's impossible~!!" << endl;//无解 57 else if(op == 0) cout << 1 << endl; 58 else cout << (1 << op) << endl; 59 } 60 61 int y[30], z[30]; 62 63 int main(void){ 64 int t, n; 65 string s; 66 cin >> t; 67 while(t--){ 68 cin >> n; 69 equ = var = n; 70 for(int i = 0; i < n; i++){ 71 cin >> y[i]; 72 } 73 for(int i = 0; i < n; i++){ 74 cin >> z[i]; 75 } 76 for(int i = 0; i < n; i++){ 77 a[i][n] = (y[i] != z[i]); 78 a[i][i] = 1; 79 x[i] = 0; 80 } 81 int cnt1, cnt2; 82 while(cin >> cnt1 >> cnt2 && cnt1 && cnt2){ 83 a[--cnt2][--cnt1] = 1; 84 } 85 solve(); 86 memset(a, 0, sizeof(a)); 87 } 88 return 0; 89 }
我就是我,颜色不一样的烟火 --- geloutingyu