最近入手一本神书 上交教练编的,一共四本,我买的是全模版那套。
翻开一看第2节就是高斯消元,正好我不会,就拿题来练手。
昂。。。打开题一看,蒙的一B啊。。这和高斯消元有毛关系啊。。。
仔细想想,如果x1动了一次,那么x2也会动一次,
那么对于x2来说,它动的次数=sum(x1+x2+....xn),
这题求的是自由元的个数,所以与sum是多少无关,所以令sum=u[i]^v[i]就行了,
代码中r是矩阵的秩,n-r就是自由元的个数了。每一个自由元有2种出现的方式,结果就是1<<n-r。
对于r以下的行,必定全是0,那么如果a[i][n]!=0 必然出现矛盾,于是判定无解。
#include<stdio.h> #include<math.h> #include<iostream> #define eps 1e-7 using namespace std; double a[110][110],as[110]; int n,u[110],v[110]; bool l[110]; int gauss(){ int i,j,k,r=0; double tmp; for(i=0;i<n;i++) l[i]=0; for(i=0;i<n;i++){ for(j=r;j<n;j++) if(fabs(a[j][i])>eps){ for(k=i;k<=n;k++) swap(a[j][k],a[r][k]); break; } if(fabs(a[r][i])<eps)continue; for(j=0;j<n;j++) if(j!=r&&fabs(a[j][i])>eps){ tmp=a[j][i]/a[r][i]; for(k=i;k<=n;k++) a[j][k]-=tmp*a[r][k]; } l[i]=1;r++; } for(i=0;i<n;i++)if(l[i]) for(j=0;j<n;j++) if(fabs(a[j][i])>eps) as[i]=a[j][n]/a[j][i]; for(i=r;i<n;i++)if(fabs(a[i][n])>eps)return -1; return 1<<n-r; } int main(){ int i,j,x,y,cs; scanf("%d",&cs); while(cs--){ scanf("%d",&n); for(i=0;i<=n;i++) for(j=0;j<=n;j++) a[i][j]=0; for(i=0;i<n;i++) scanf("%d",&u[i]); for(i=0;i<n;i++){ scanf("%d",&v[i]); a[i][n]=u[i]^v[i]; a[i][i]=1; } while(scanf("%d%d",&i,&j),i||j) a[j-1][i-1]=1; x=gauss(); if(x==-1)puts("Oh,it's impossible~!!"); else printf("%d\n",x); } return 0; }
总感觉用int不稳妥。。虽然这题都是1 0,貌似不存在小数的情况,但我还是用double做了。。