poj 1830 高斯消元
来源:互联网 发布:不要域名能建网站么 编辑:程序博客网 时间:2024/04/29 18:16
题意:有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,那么无解,否则唯一解
using namespace std;#define LL long longconst 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=row - 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][n]); for(int i=0;i<n;i++) { int x; scanf("%d",&x); a[i][n]^=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;}
阅读全文
0 0
- poj 1830(高斯消元求解。。。。)
- POJ 1830 高斯消元
- poj 1830 高斯消元
- poj 1830(高斯消元)
- POJ 1830(高斯消元)
- POJ 1830 (高斯消元)
- poj 1830 高斯消元
- 数学 --- 高斯消元 POJ 1830
- poj 1830 高斯消元
- POJ 1830 开关问题 高斯消元
- poj 1830 开关问题 高斯消元
- poj 1830 开关问题 高斯消元
- POJ 1830 开关问题 (高斯消元)
- POJ 1830 开关问题 (高斯消元)
- poj 1830 开关问题(高斯消元)
- poj 1830 开关问题 高斯消元
- [高斯消元] poj 1830 开关问题
- POJ 1830 开关问题(高斯消元)
- c++ vector容器的使用
- C++ virtual
- 1002 A + B Problem II
- 数据结构实验之二叉树四:(先序中序)还原二叉树
- es6->array&number
- poj 1830 高斯消元
- 程序员,该如何避免成为一个“油腻的怪物”
- 阅读Android framework源代码方式
- Maximum Swap:交换数字中的任意两位一次使其尽可能变大
- Android画板开发(五) 添加文本文字
- 路由表
- 挑战万兆网卡性能 品高以虚战实
- centos7部署Openresty,使用certbot-nginx进行https支持
- 示例:用户登录(python版)