洛谷 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‘。
输入输出样例
10 1 -1 7 -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