洛谷 P1468 [USACO2.2]派对灯 Party Lamps

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1468 [USACO2.2]派对灯 Party Lamps相关的知识,希望对你有一定的参考价值。

题目描述

在IOI98的节日宴会上,我们有N(10<=N<=100)盏彩色灯,他们分别从1到N被标上号码。 这些灯都连接到四个按钮:

按钮1:当按下此按钮,将改变所有的灯:本来亮着的灯就熄灭,本来是关着的灯被点亮。

按钮2:当按下此按钮,将改变所有奇数号的灯。

按钮3:当按下此按钮,将改变所有偶数号的灯。

按钮4:当按下此按钮,将改变所有序号是3*K+1(K>=0)的灯。例如:1,4,7...

一个计数器C记录按钮被按下的次数。当宴会开始,所有的灯都亮着,此时计数器C为0。

你将得到计数器C(0<=C<=10000)上的数值和经过若干操作后某些灯的状态。写一个程序去找出所有灯最后可能的与所给出信息相符的状态,并且没有重复。

输入输出格式

输入格式:

 

不会有灯会在输入中出现两次。

第一行: N。

第二行: C最后显示的数值。

第三行: 最后亮着的灯,用一个空格分开,以-1为结束。

第四行: 最后关着的灯,用一个空格分开,以-1为结束。

 

输出格式:

 

每一行是所有灯可能的最后状态(没有重复)。每一行有N个字符,第1个字符表示1号灯,最后一个字符表示N号灯。0表示关闭,1表示亮着。这些行必须从小到大排列(看作是二进制数)。

如果没有可能的状态,则输出一行‘IMPOSSIBLE‘。

 

输入输出样例

输入样例#1:
10
1
-1
7 -1
输出样例#1:
0000000000
0101010101
0110110110

说明

在这个样例中,有三种可能的状态:

所有灯都关着

1,4,7,10号灯关着,2,3,5,6,8,9亮着。

1,3,5,7,9号灯关着,2, 4, 6, 8, 10亮着。

翻译来自NOCOW

USACO 2.2

 

【分析】

又是一道很有意思的题,懒得打题解了就搬一个讲得最详细的来吧。

··· 以下是nocow思路:

每个按钮按2次和没按效果是一样的。所以每个按钮或者按或者不按,一共有2^4=16种状态。枚举每个按钮是否按下,然后生成结果,排序输出即可(注意判重)。

另外灯1和灯7,2和8,3和9...是一样的因此当N>=6时只需处理前6个,排序时转换为10进制数, 输出时反复输出前6个的状态.

深究:

这道题如果深究的话会变得非常简单, 但是提前声明,如果对这道题兴趣不大,或者是初学者,建议跳过, 刚才的分析已经足以过这道题。 我们现在记不按按钮,以及按下1,2,3,4按钮分别O,①,②,③,④, 那么,按下3,4,可以记为③④,以此类推, 我们发现一个问题,那就是①,②,③之间微妙的关系, ①②=③,而②③=①,①③=②(可以自己试试),于是我们知道,①②③也相当与不按,即相差3的倍数也可互相转换;

所以,所谓前四个的16种按法其实只有8种, 分别为:O,①,②,③,④,①④,②④,③④;

然后讨论c, 由于当c>4时,均可化为当c<=4的情况, 所以我们先讨论当c<=4的情况,

当c=0时,只有一种O;

当c=1时,四种:①,②,③,④;

当c=2时,除了④均可(可以自己想想);

当c=3时,由于3-1=2,所以c=1的情况都满足,而在c=2中,把所有有前三类的展开,如①④变为②③④, 可知满足c=2的同时满足c=3,所以c=3其实是c=2和c=1的并集,即所有按法均可。

当c=4时,由于4-1=3(①②③相当于不按),且4-2=2,由上,c=4也是所有按法均可。

当c>4时,我先有一个引理:对于任意的正整数n>1,均可写成n=2*p+3*q(p,q为非负整数)的形式, 证明如下:若n为偶数,必然成立,若n为奇数,必然大于2,则n-3必为非负偶数,得证。 由这个引理我们可以知道,任意c>4均可写成,c=2*p+3*q+3(p,q为非负整数)的形式,而可知, 对于两个相同的按键,以及情况①②③(按键三次),均相当于不按,所以任意c>4均可化归为c=3的情况, 即当c>4时,所有按法均可。

综上所述,

当c=0时,只有一种O;

当c=1时,四种:①,②,③,④;

当c=2时,除了④均可;

当c>2时,所有按法均可。

好了,这样一来就非常简单了, 只有四种情况,8种按法。

 

【代码】

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int a[10][10]={{}, {0, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0}, {0, 0, 1, 0, 1, 0, 1}, {0, 0, 1, 1, 0, 1, 1}, {0, 1, 0, 0, 1, 0, 0}, {0, 1, 0, 1, 0, 1, 0}, {0, 1, 1, 0, 0, 0, 1}};
 5 int n, c, op[10], cl[10], x;
 6 bool flag;
 7 
 8 void init() {
 9     cin >> n >> c;
10     c=min(3, c);
11     memset(op, 0, sizeof(op));
12     memset(cl, 1, sizeof(cl));
13     while (scanf("%d", &x)==1) {
14         if (x==-1)
15             break;
16         op[x%6?x%6:6]=1;
17     }
18     while (scanf("%d", &x)==1) {
19         if (x==-1)
20             break;
21         cl[x%6?x%6:6]=0;
22     }
23 }
24 
25 void check(int t) {
26     for (int i=1;i<=6;++i)
27         if ((op[i] && !a[t][i]) || (!cl[i] && a[t][i]))
28             return;
29     flag=true;
30     for (int i=1;i<=n;++i)
31         printf("%d", a[t][i%6?i%6:6]);
32     printf("\n");
33 }
34 
35 void sovle() {
36     if (c==0)
37         check(1);
38     else if (c==1)
39         check(2), check(4), check(5), check(7);
40     else if (c==2)
41         check(2), check(3), check(4), check(6), check(7), check(8), check(1);
42     else
43         check(2), check(3), check(4), check(5), check(6), check(7), check(8), check(1);
44     if (!flag)
45         cout << "IMPOSSIBLE" << endl;
46 }
47 
48 int main() {
49     init();
50     sovle();
51 }

 

以上是关于洛谷 P1468 [USACO2.2]派对灯 Party Lamps的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1466 [USACO2.2]集合 Subset Sums

洛谷 P1467 [USACO2.2]循环数 Runaround Numbers

洛谷 P1465 [USACO2.2]序言页码 Preface Numbering

[洛谷201704R1]开心派对小火车

洛谷——P1821 [USACO07FEB]银牛派对Silver Cow Party

洛谷 P1821 [USACO07FEB]银牛派对Silver Cow Party