【poj1830-开关问题】高斯消元求解异或方程组

第一道高斯消元题目~

题目:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)0<=N<=29

我们用样例来模拟一下:

我的高斯消元求解异或方程组模版:

 1 int gauss()
 2 {
 3     int i,j,k,l;
 4     //j=当前要消第几个元
 5     //i=当前消了几个元+1(n-i+1就是自由元个数),也就是当前j要处理的这个方程将要放在第i行,构成上三角矩阵。
 6     //i、j不等是因为有些元是自由元,不需要消,这些方程放到最后面(维护上三角矩阵)。
 7     for(i=1,j=1;i<=n && j<=n;j++)
 8     {
 9         for(k=j;k<=n;k++)
10             if(a[k][j]) break;//先找到一个这个元的系数不为0方程的换到第i行。
11         if(a[k][j])
12         {
13             for(l=1;l<=n+1;l++) swap(a[i][l],a[k][l]);
14             for(l=i+1;l<=n;l++)
15             {
16                 if(a[l][j])//如果系数不为0才异或消元
17                     for(k=1;k<=n+1;k++)
18                         a[l][k]^=a[i][k];
19             }
20             i++;
21         }
22     }
23     for(j=i;j<=n;j++)
24         if(a[j][n+1]) return -1;
25     return 1<<(n-i+1);
26 }

说一下解的个数问题:

对增广矩阵[A b]做初等行变换,化成阶梯形(高斯消元法),如果存在[0,0,…,0,1]的行,就是无解;如果存在r行[0,0,…,0,0],就意味着有r个自由变量,因为这里的变量只取0/1,所以有2r个解;如果不存在[0,0,…,0,*],即把最后一行去掉后不存在全0行,则A为满秩矩阵,则方程组有唯一解。

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8
 9 const int N=35;
10 int n,bit[N],a[N][N];
11
12 void output()
13 {
14     for(int i=1;i<=n;i++)
15     {
16         for(int j=1;j<=n+1;j++)
17             printf("%d ",a[i][j]);
18         printf("\n");
19     }
20     printf("\n");
21 }
22
23 int gauss()
24 {
25     int i,j,k,l;
26     //j=当前要消第几个元
27     //i=当前消了几个元+1(n-i+1就是自由元个数),也就是当前j要处理的这个方程将要放在第i行,构成上三角矩阵。
28     //i、j不等是因为有些元是自由元,不需要消,这些方程放到最后面(维护上三角矩阵)。
29     for(i=1,j=1;i<=n && j<=n;j++)
30     {
31         for(k=j;k<=n;k++)
32             if(a[k][j]) break;//先找到一个这个元的系数不为0方程的换到第i行。
33         if(a[k][j])
34         {
35             for(l=1;l<=n+1;l++) swap(a[i][l],a[k][l]);
36             for(l=j+1;l<=n;l++)
37             {
38                 if(a[l][j])//如果系数不为0才异或消元
39                     for(k=1;k<=n+1;k++)
40                         a[l][k]^=a[i][k];
41             }
42             i++;
43         }
44     }
45     for(j=i;j<=n;j++)
46         if(a[j][n+1]) return -1;
47     return 1<<(n-i+1);
48 }
49
50 int main()
51 {
52     int T,x,y;
53     scanf("%d",&T);
54     while(T--)
55     {
56         scanf("%d",&n);
57         memset(a,0,sizeof(a));
58         for(int i=1;i<=n;i++) scanf("%d",&a[i][n+1]);
59         for(int i=1;i<=n;i++)
60         {
61             scanf("%d",&x);
62             a[i][n+1]^=x;
63         }
64         while(1)
65         {
66             scanf("%d%d",&x,&y);
67             if(!x && !y) break;
68             a[y][x]=1;
69         }
70         for(int i=1;i<=n;i++) a[i][i]=1;
71         int ans=gauss();
72         if(ans==-1) printf("Oh,it‘s impossible~!!\n");
73         else printf("%d\n",ans);
74     }
75     return 0;
76 }
时间: 2024-08-10 02:58:21

【poj1830-开关问题】高斯消元求解异或方程组的相关文章

高斯消元求解异或方程组

POJ1830 开关问题 对于解异或方程组,系数可以采用二进制压缩,如果系数太多可以使用bitset,但是如果少一点就可以使用下述的写法,更加简单快速 使用bitset的写法更正常的没什么区别,只是对应的消除变为异或操作,另外行变换也会更加简单 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int a[100

POJ 1222-EXTENDED LIGHTS OUT(高斯消元求解异或方程组)

题目地址:POJ 1222 题意:有一个5*6的矩阵,每个位置都表示按钮和灯,1表示亮,0表示灭.每当按下一个位置的按钮,它和它周围灯的状态全部翻转(题目中给出如何影响),问在这样的一个方阵中按下哪些按钮可以把整个方阵都变成灭的,这时1表示按了,0表示没按. #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream>

BZOJ 3563 DZY Loves Chinese / BZOJ 3569 DZY Loves Chinese II 随机化+高斯消元解异或方程组

题目大意:给出一个无向图,问删掉k条边的时候,图是否联通. 思路:虽然我把这两个题放在了一起,但是其实这两个题可以用完全不同的两个解法来解决. 第一个题其实是DZY出错了...把每次的边数也异或了,那就直接用这个性质一个一个往后推就行了..最后一个暴力求一下.. 第二个题才是本意啊. 听到做法的时候我惊呆了.. 首先是将整个图中拆出一个树,那么所有边就分为树边和非树边.将所有非树边都加一个随机权值.树边的权值是所有能够覆盖它的非树边的权值的异或和. 把整个图拆开的充要条件是拆掉一条树边,同时将所

【BZOJ2466】【中山市选2009】树 高斯消元解异或方程组

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44356273"); } 题解: 参照此题解,也是我写的,俩题一样. [POJ1681]Painter's Problem 高斯消元,求最小∑系数的异或方程组 代码: #include <cmath> #include &

[POJ1830]开关问题(高斯消元,异或方程组)

题目链接:http://poj.org/problem?id=1830 题意:中文题面,求的是方案数. 首先可以知道, 如果方案数不止一个的话,说明矩阵行列式值为0,即存在自由变元,由于变量只有两种状态,那么方案数就是2^自由变元数. 从起始状态到终止状态,只需要关心起始和终止哪些状态不一样就行,也就是翻转奇数次. 由于是倒推,所以开关的影响要反过来存. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long lon

Hdu 5833 Zhu and 772002(高斯消元解异或方程组)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5833 思路: 将每个数质因数分解,若该位质因数指数为偶数,则该位a[i]为0,否则该位a[i]为1(记a[i]为质因数分解后第i个质数所对应值). 合法方案为积的各位质因子个数对应值a[i]异或值为0. 例3=3^1,4=2^2,则3*3*4对应: 2           3 0   (1 xor 1=0) 则可列方程组 a11x1+a12x2+...+a1nxn=0 a21x1+a22x2+...

【poj2947】高斯消元求解同模方程组【没有AC,存代码】

题意: p start enda1,a2......ap (1<=ai<=n)第一行表示从星期start 到星期end 一共生产了p 件装饰物(工作的天数为end-start+1+7*x,加7*x 是因为它可能生产很多周),第二行表示这p 件装饰物的种类(可能出现相同的种类,即ai=aj).规定每件装饰物至少生产3 天,最多生产9 天.问每种装饰物需要生产的天数.如果没有解,则输出"Inconsistent data.",如果有多解,则输出"Multiple so

poj 1830 开关问题 高斯消元

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

行列式 &amp; 高斯消元求解行列式

行列式 \[D = \left| \begin{array}{c} a_{11} & a_{12} & a_{13} \a_{21} & a_{22} & a_{23} \a_{31} & a_{32} & a_{33} \\end{array} \right|\] 上图是一个三阶行列式,行列式是形如上图的一个东西,简记为: \(det(a_{ij})\), 其中\(a_{ij}\)是行列式的第\(ij\)元. 一个n阶行列式的值为: \[\sum (-1)