1. 程式人生 > >洛谷 P1468 [USACO2.2]派對燈 Party Lamps

洛谷 P1468 [USACO2.2]派對燈 Party Lamps

lamp else 有一個 題解 sca std 顯示 程序 con

題目描述

在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