POJ1830开关问题

这题答案就是2^自由元的数目,原因是自由元可以取1或者0,所以就是ans<<1

由于只要求自由元的数目,所以高斯消元可以直接消后面的,不做前面的了,对答案没有影响

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define MAXN 35
 6 using namespace std;
 7 int a[MAXN][MAXN];
 8 int gauss(int m,int n){
 9     int ret=0,line=1;
10     for(int k=1;k<=m;k++){
11         int i=line;
12         while(i<=m){if(a[i][k])break;i++;}
13         if(i>m){ret++;continue;}//自由元 
14         if(i!=line){for(int j=k;j<=n;j++)swap(a[i][j],a[line][j]);}
15         for(i=line+1;i<=m;i++){
16             if(a[i][k]){
17                 for(int j=k;j<=n;j++){
18                     a[i][j]^=a[line][j];
19                 }
20             }
21         }
22         line++;
23     }
24     for(int i=line;i<=m;i++)if(a[i][n])return -1;
25     //最后一定都消成0了,所以a[i][n]必须为0才符合题意 
26     return ret;
27 }
28 int n;
29 void solve(){
30     memset(a,0,sizeof(a));
31     scanf("%d",&n);
32     for(int i=1;i<=n;i++)scanf("%d",&a[i][n+1]);
33     int x,y;
34     for(int i=1;i<=n;i++){scanf("%d",&x);a[i][n+1]^=x;}
35     for(int i=1;i<=n;i++){a[i][i]=1;}
36     while(1){
37         scanf("%d%d",&x,&y);
38         if(!x&&!y)break;
39         a[y][x]=1;
40     }
41     int ans=gauss(n,n+1);
42     if(-1==ans)printf("Oh,it's impossible~!!
");
43     else printf("%d
",1<<ans);
44 }
45 int main()
46 {
47 //    freopen("data.in","r",stdin);
48     int T;
49     scanf("%d",&T);
50     while(T--){
51         solve();
52     }
53     return 0;
54 }
原文地址:https://www.cnblogs.com/w-h-h/p/8278150.html