pro:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)
sol:即求自由元的个数,答案是pow(2,自由元)。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; int a[30][30],ans[30]; int Guass(int N) { int res=0; rep(i,0,N-1){ int mark=i; rep(j,i+1,N-1) if(abs(a[j][i])>abs(a[mark][i])) mark=j; if(mark!=i) rep(j,0,N) swap(a[i][j],a[mark][j]); if(!a[i][i]){ res++; continue;} //自由元 rep(j,i+1,N){ if(!a[j][i]) continue; rep(k,i,N){ a[j][k]^=a[i][k]; } } } for(int i=N-1;i>=0;i--){ if(!a[i][i]&&a[i][N]) return -1;//无解 ans[i]=a[i][N]&a[i][i]; rep(j,0,i-1) a[j][N]^=(a[j][i]&ans[i]); } return 1<<res; } int s[300],t[300],res; int main() { int T,N,u,v; scanf("%d",&T); while(T--){ memset(a,0,sizeof(a)); scanf("%d",&N); rep(i,0,N-1) scanf("%d",&s[i]); rep(i,0,N-1) scanf("%d",&t[i]); rep(i,0,N-1) a[i][N]=s[i]^t[i],a[i][i]=1; while(~scanf("%d%d",&u,&v)&&u+v!=0){ a[v-1][u-1]=1; //二者不要写反 } int res=Guass(N); if(res==-1) puts("Oh,it's impossible~!!"); else printf("%d\n",res); } return 0; }