开关问题
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 8714   Accepted: 3424

Description

有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~!!” 不包括引号

Sample Input

2
3
0 0 0
1 1 1
1 2
1 3
2 1
2 3
3 1
3 2
0 0
3
0 0 0
1 0 1
1 2
2 1
0 0

Sample Output

4
Oh,it's impossible~!!

Hint

第一组数据的说明: 
一共以下四种方法: 
操作开关1 
操作开关2 
操作开关3 
操作开关1、2、3 (不记顺序) 

题目链接:POJ 1830

比较裸的一道题,记得开关自己跟自己是有关系的,即Mat[i][i]要恒为1,用高斯消元在判断了自由变量之后如果还出现非0系数,则说明无解,如果有解即有$freenum$个自由变量,那么显然每一个自由变量是随意取值的,每一个都取0或1,那么答案显然是$2^{freenum}$个

如何列方程呢?两边同时异或一下开始的状态即可以得到目标的状态,因为S->T的操作和0->(S xor T)的操作是一样的

代码:

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <sstream>
#include <numeric>
#include <cstring>
#include <bitset>
#include <string>
#include <deque>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 31;
int Mat[N][N]; int Gaussian(int ne, int nv)
{
int ce, cv, i, j;
for (ce = 1, cv = 1; ce <= ne && cv <= nv; ++ce, ++cv)
{
int te = ce;
for (i = ce + 1; i <= ne; ++i)
if (Mat[i][cv] > Mat[te][cv])
te = i;
if (te != ce)
{
for (i = cv; i <= nv + 1; ++i)
swap(Mat[ce][i], Mat[te][i]);
}
if (!Mat[ce][cv])
{
--ce;
continue;
}
for (i = ce + 1; i <= ne; ++i)
{
if (Mat[i][cv])
{
for (j = cv; j <= nv + 1; ++j)
Mat[i][j] ^= Mat[ce][j];
}
}
}
for (i = ce; i <= ne; ++i)
if (Mat[i][cv])
return -1;
return nv - (ce - 1);
}
int main(void)
{
int tcase, n, i;
scanf("%d", &tcase);
while (tcase--)
{
CLR(Mat, 0);
scanf("%d", &n);
for (i = 1; i <= n; ++i)
{
scanf("%d", &Mat[i][n + 1]);
Mat[i][i] = 1;
}
for (i = 1; i <= n; ++i)
{
int x;
scanf("%d", &x);
Mat[i][n + 1] ^= x;
}
int a, b;
while (~scanf("%d%d", &a, &b) && (a || b))
Mat[b][a] = 1;
int frnum = Gaussian(n, n);
frnum == -1 ? puts("Oh,it's impossible~!!") : printf("%d\n", 1 << frnum);
}
return 0;
}

POJ 1830 开关问题(高斯消元求解的情况)的更多相关文章

  1. POJ 1830 开关问题 高斯消元,自由变量个数

    http://poj.org/problem?id=1830 如果开关s1操作一次,则会有s1(记住自己也会变).和s1连接的开关都会做一次操作. 那么设矩阵a[i][j]表示按下了开关j,开关i会被 ...

  2. POJ 1830 开关问题 (高斯消元)

    题目链接 题意:中文题,和上篇博客POJ 1222是一类题. 题解:如果有解,解的个数便是2^(自由变元个数),因为每个变元都有两种选择. 代码: #include <iostream> ...

  3. POJ 1830 开关问题 [高斯消元XOR]

    和上两题一样 Input 输入第一行有一个数K,表示以下有K组测试数据. 每组测试数据的格式如下: 第一行 一个数N(0 < N < 29) 第二行 N个0或者1的数,表示开始时N个开关状 ...

  4. POJ.1830.开关问题(高斯消元 异或方程组)

    题目链接 显然我们需要使每个i满足\[( ∑_{j} X[j]*A[i][j] ) mod\ 2 = B[i]\] 求这个方程自由元Xi的个数ans,那么方案数便是\(2^{ans}\) %2可以用^ ...

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

    第一道高斯消元题目~ 题目:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关 ...

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

    题意: p start enda1,a2......ap (1<=ai<=n)第一行表示从星期start 到星期end 一共生产了p 件装饰物(工作的天数为end-start+1+7*x, ...

  7. 【zoj3645】高斯消元求解普通线性方程

    题意: 给你一个方程组(含有12个方程),求(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11) 方程组的形式是一个二次方程组 (ai1-x1)^2 + (ai2-x2)^2 +( ...

  8. POJ 1222 POJ 1830 POJ 1681 POJ 1753 POJ 3185 高斯消元求解一类开关问题

    http://poj.org/problem?id=1222 http://poj.org/problem?id=1830 http://poj.org/problem?id=1681 http:// ...

  9. POJ 3185 The Water Bowls 【一维开关问题 高斯消元】

    任意门:http://poj.org/problem?id=3185 The Water Bowls Time Limit: 1000MS   Memory Limit: 65536K Total S ...

随机推荐

  1. 【HDU1542】Atlantis (扫描线的经典运用)

    点此看题面 大致题意: 给你\(N\)个矩形,请你求出它们覆盖的面积(重叠的面积只算一次). 扫描线 这道题是一道典型的求矩形面积并问题,是扫描线的一个经典运用.这里就不赘述了. 代码 #includ ...

  2. C/C++语言补缺 宏- extern "C"-C/C++互调

    1. 宏中的# 宏中的#的功能是将其后面的宏参数进行字符串化操作(Stringizing operator),简单说就是在它引用的宏变量的左右各加上一个双引号. 如定义好#define STRING( ...

  3. 在C++类中使用dllimport和dllexport导出,

    在Windows平台下: 您可以使用dllimport或dllexport属性声明C ++类.这些形式意味着导入或导出整个类.以这种方式导出的类称为可导出类. 以下示例定义可导出的类.导出其所有成员函 ...

  4. 题解 P2626 【斐波那契数列(升级版)】

    这道题,大家一定要注意: 要对2^31取模 ! ( 本蒟蒻开始没注意到这一点,WA了 ) (不过大家在试样例的时候,试试47,出不了结果,就说明你没模2^31) 总体来说,这道题考查的知识点就两个: ...

  5. 1025: [SCOI2009]游戏

    Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2727  Solved: 1794[Submit][Status][Discuss] Descripti ...

  6. MySql学习笔记02

    MySql02 复习 数据库相关 连接数据库的命令 mysql -uroot -p 创建数据库 create database db2; 查询所有的数据库 show databases; 查询单个数据 ...

  7. 九、Shell 流程控制

    Shell 流程控制 和Java.PHP等语言不一样,sh的流程控制不可为空,如(以下为PHP流程控制写法): <?php if (isset($_GET["q"])) { ...

  8. 多种方式实现依赖注入及使用注解定义bean

    构造注入 如何给构造方法中的参数注入方法呢如下 首先bean代码如下 package cn.pojo; public class Greeting { /** * 说的话 */ private Str ...

  9. hprose 1.0(rpc 框架) - 执行时序图

  10. 23.VUE学习之-列表的排序sort

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...