暑期实践日志(三)

开关问题

Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 6455   Accepted: 2463

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 (不记顺序)

Source

[email protected]

这到题目是高斯消元法的典型应用。

将将所有开关之间的关系当做系数,而对于开关的操作则作用为变量。

这样就形成了系数矩阵和变量矩阵。需要注意的是系数矩阵中每一行中的值a[i][j]表示的是j对i是否有影响。

代码:

zfy11 ‘s source code for B

Memory: 148 KB   Time: 0 MS
Language: C++   Result: Accepted
Public:   No Yes

Select All

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<iostream>
using namespace std;
const int maxn=60;
int a[maxn][maxn];
int x[maxn];
int free_x[maxn];
int gauss(int equ,int var)
{
    int i,j,k,max_r,col;
    for(int i=0;i<=var;i++)
    {
        x[i]=0;
        free_x[i]=1;
    }
    col=0;
    for(k=0;k<equ&&col<var;k++,col++)
    {
        max_r=k;
        for(i=k+1;i<equ;i++)
        {
            if(abs(a[i][col])>abs(a[max_r][col]))
                max_r=i;
        }
        if(max_r!=k)
        {
            for(j=k;j<var+1;j++)
                swap(a[k][j],a[max_r][j]);
        }
        if(a[k][col]==0)
        {
            k--;
            continue;
        }
        for(i=k+1;i<equ;i++)
        {
            if(a[i][col]!=0)
            {
                for(j=col;j<var+1;j++)
                    a[i][j]^=a[k][j];
            }
        }
    }
    for(i=k;i<equ;i++)
    {
        if(a[i][col]!=0)
            return -1;
    }
    return var-k;
}
int start[maxn];
int end[maxn];
int main()
{
    int n;
    int s,e;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&start[i]);
        }
        for(int i=0;i<n;i++)
        {
            scanf("%d",&end[i]);
        }
        memset(a,0,sizeof(a));
        while(scanf("%d%d",&s,&e))
        {
            if(s==0&&e==0)
                break;
            a[e-1][s-1]=1;
        }
        for(int i=0;i<n;i++)
            a[i][i]=1;
        for(int i=0;i<n;i++)
            a[i][n]=start[i]^end[i];
        int ans=gauss(n,n);
        if(ans==-1)
            printf("Oh,it‘s impossible~!!\n");
        else
            printf("%d\n",1<<ans);
    }
    return 0;
}
时间: 2024-08-01 22:45:13

暑期实践日志(三)的相关文章

暑期实践日志(五)

这道题是典型的二维线段树的题目,题目要求查询一个区间的最小值和最大值,并修改一个点. 代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<set> #include<map> #include<cstdlib> u

暑期实践日志(二)

这道题的思路是,将题目中所描述的齿轮看成是圆,其中两个齿轮相互咬合则是两个圆相切,那么根据判断两个圆相切的方法来判断两个齿轮间是否咬合.其中还会用到齿轮传动的规律,即传动轮的速度由主动轮来决定,根据该题的描述可知所有齿轮中只有一个是主动轮,那么其他齿轮的速度都都它决定,随度的比值就是R1/Ri. 代码: #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #inc

暑期实践日志(四)

Painter's Problem Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4912   Accepted: 2385 Description There is a square wall which is made of n*n small square bricks. Some bricks are white while some bricks are yellow. Bob is a painter and

暑期实践日志(一)

2015年7月6日 题解这道题目是一个数学题,其中有两个需要注意的地方. 第一:题目要求我们求将一个数分解成连续数字的和,而且要求数字个数最少.由题目意思可以推导出一个公式,所给的数N=(a+(a+k-1))/2.其中的a表示连续数字和中最小的那个数,k表示的是连续数字的个数,整个公式的由来是等差数列求和公式推导的. 第二:在求解时,虽然已经推导出了公式,但是在求解时,根据公式,我们采取遍历所有的k的值来求解a,如果从2到n遍历的话会超时.所以这里要注意,要从2到2*n开根号,这样可以避免超时.

Agile实践日志一 -- Grooming Session

Agile实践日志一  -- Grooming Session GroomingSession 这个Session主要Go through我们下一个Sprint须要做的Story,大家都清楚之后,在每一个Story最后我们会以 Good Agile 扑克牌来确认它的难度点.在sprint之前,做一个story的评估和规划,为接下来分story提供难度系数的參照. Story Story是敏捷的核心.一切task来自story,我们仅仅有制定了story.才干确定task.一切測试工作也是基于st

实践GTD三周年后的体会

从2011年7月开始实践GTD到现在已经3年多了,按照年初设定的目标,应该写点GTD的体会,但提起笔来的时候却发现并没有什么太新的体会,大部分体会都已经在以前的文章中写到了,甚至有些流程已经简化了,看来这篇文章也就是把以前的文章再梳理一遍. 1.GTD到底是什么? GTD是一种时间管理的系统性方法,一方面让你全面掌控工作和生活中的事务,减轻焦虑,提高效率,另一方面让你把握视角,让你把主要精力集中在有意义的事情上. 这本<搞定III>中的下面这张图用2个维度说明了这种理念,水平方向上你用GTD的

Git工程开发实践(三)——Git常用操作

Git工程开发实践(三)--Git常用操作 一.Git仓库操作 1.Git仓库创建 git init在当前目录中初始化Git仓库git init [project-name]创建一个新目录并初始化仓库初始化git仓库会默认创建一个mater分支,创建名为.git的子目录,内含初始化Git仓库中所有的骨干文件,此时仓库中的文件还没有被跟踪.通过git add命令来实现对指定文件的跟踪,然后执行git commit提交. git add . git commit -m 'initial projec

android 实践项目三

android 实践项目三 本周我主要完成的任务是将代码进行整合,然后实现百度地图的定位与搜索功能.在这次实现的 图形界面如下: 在本周的工作中主要的实现出来定位与收索的功能,在地图中能实现了定位,显示当前的位置, 不知到为什么不显示地图,经过查找资料可能因为当前的SDK本版太高了,不匹配.所以在下周 图像的显示问题.下面是我的主要贴上我的布局代码 地图的布局: 本周的总结 做项目是学习知识最快的方式,即能让我们碰见各种问题,也让我们去解决各种问题.在项目中感觉自己 的水平有限,还需要更加努力的

JavaScript网站设计实践(三)设计有特色的主页,给主页链接添加JavaScript动画脚本

原文:JavaScript网站设计实践(三)设计有特色的主页,给主页链接添加JavaScript动画脚本 一.主页一般都会比较有特色,现在在网站设计(二)实现的基础上,来给主页添加一点动画效果. 1.这里实现的动画效果是:当鼠标悬停在其中某个超链接时,会显示出属于该页面的背景缩略图,让用户知道这个链接的页面大概内容是什么. 效果图: 2.实现这个效果的思路 (1)把主页的几个链接的背景图片缩放到150px*150px,拼成一张750*150的图片,并保存为slideshow.png,存放到ima