poj 1830 高斯消元
2017-11-02 09:34
288 查看
题意:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)
Input
输入第一行有一个数K,表示以下有K组测试数据。
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。
Output
如果有可行方法,输出总数,否则输出“Oh,it’s impossible~!!” 不包括引号
分析:这个题和前面5*6的按钮问题很像。这个就多了要输出方案数。就等价于我们求解矩阵的时候,如果行多于列的话,那么有自由元,每个自由元都可以取0或1,如果那一行中之后最后a[r][c]!=0,那么无解,否则唯一解
Input
输入第一行有一个数K,表示以下有K组测试数据。
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。
Output
如果有可行方法,输出总数,否则输出“Oh,it’s impossible~!!” 不包括引号
分析:这个题和前面5*6的按钮问题很像。这个就多了要输出方案数。就等价于我们求解矩阵的时候,如果行多于列的话,那么有自由元,每个自由元都可以取0或1,如果那一行中之后最后a[r][c]!=0,那么无解,否则唯一解
using namespace std; #define LL long long const int maxn = 100; int a[maxn][maxn]; int x[maxn]; bool freex[maxn]; int gcd(int a,int b) { return b?gcd(b,a%b):a; } int lcm(int a,int b) { return a/gcd(a,b)*b; } int gauss(int rn,int cn) { for(int i=0;i<=cn;i++){ x[i]=0; freex[i]=true; } int col = 0; int row = 0; int maxrow; for(;row<rn&&col<cn;row++,col++) { maxrow = row; for(int i = row+1;i<rn;i++) { if(abs(a[i][col])>abs(a[maxrow][col])) maxrow=i; } if(maxrow!=row) { for(int j=row;j<=cn;j++) swap(a[row][j],a[maxrow][j]); } if(a[row][col]==0) { row--; continue; } for(int i=row+1;i<rn;i++) { if(a[i][col]!=0) { for(int j=col;j<=cn;j++) { a[i][j]=a[row][j]^a[i][j]; } } } } //无解的情况 for(int i=row;i<rn;i++) { if(a[i][col]!=0) return -1; } //无穷解的情况 if(row < cn) { for(int i=r 4000 ow - 1;i>=0;i--) { int freeNum=0; int freeIndex = 0; for(int j=0;j<cn;j++) { if(a[i][j]!=0&&freex[j]) { freeNum++; freeIndex = j; } } if(1<freeNum) continue; x[freeIndex] = a[i][cn]; for(int j=0;j<cn;j++) { if(a[i][j]!=0&&j!=freeIndex) x[freeIndex]^=(a[i][j]&&x[j]); } // x[freeIndex]= tmp/a[i][freeIndex]; freex[freeIndex]=false; } return cn-row; } for(int i=cn-1;i>=0;i--) { x[i]= a[i][cn]; for(int j=i+1;j<cn;j++) { if(a[i][j]!=0) { x[i]^=(a[i][j]&&x[j]); } } } return 0; } LL pow1(int n) { LL ans=1,q=2; while(n) { if(n&1) ans=ans*q; q=q*q; n=n/2; } return ans; } int main() { int T; scanf("%d",&T); while(T--) { memset(x,0,sizeof(x)); memset(a,0,sizeof(a)); int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i] ); for(int i=0;i<n;i++) { int x; scanf("%d",&x); a[i] ^=x; } for(int i=0;i<n;i++) a[i][i]=1; int a1,b1; while(scanf("%d %d",&a1,&b1)!=EOF) { if(a1==0&&b1==0) break; a1--,b1--; a[b1][a1]=1; } int k=gauss(n,n); if(k<0) printf("Oh,it's impossible~!!\n"); else if(k==0) printf("1\n"); else printf("%lld\n",pow1(k)); } return 0; }
相关文章推荐
- POJ 1830 开关问题 高斯消元求自由变元
- poj 1830 开关问题 1830 高斯消元
- 高斯消元 POJ 1222 POJ 1681(枚举自由变元)POJ 1753(两次高斯消元) POJ 1830 HDU 5833 (高斯消元,素数分解)POJ 3158 (集合压缩枚举自由变元)
- poj 1830 高斯消元
- poj 1830 开关问题(高斯消元)
- POJ-1830 开关问题 高斯消元 | 搜索
- poj 1830(高斯消元求解。。。。)
- [POJ 1830] 开关问题 高斯消元
- POJ 1830 开关问题 高斯消元,自由变量个数
- poj 1830 开关问题高斯消元
- POJ 1222 & 1681 & 1830 & 3185 开关灯问题 (高斯消元 & 异或方程组)
- poj 1830 开关问题(高斯消元)
- poj 1830 开关问题(高斯消元)
- 高斯消元求方案数 POJ-1830
- poj 1830 高斯消元
- poj 1222 poj 1830高斯消元解决开关问题
- poj1830 开关问题 高斯消元
- POJ 1222 & 1681 & 1830 & 3185 开关灯问题 (高斯消元 & 异或方程组)
- POJ 1830 【高斯消元第一题】
- POJ 1830 开关问题 高斯消元