题目描述
在 IOI98 的节日宴会上,我们有 n 盏彩色灯,他们分别从1∼n 被标上号码。这些灯都连接到四个按钮:
按钮 1:当按下此按钮,将改变所有的灯:本来亮着的灯就熄灭,本来是关着的灯被点亮。
按钮 2:当按下此按钮,将改变所有奇数号的灯。
按钮 3:当按下此按钮,将改变所有偶数号的灯。
按钮 4:当按下此按钮,将改变所有序号是3k+1 (k∈[0,+∞)∩Z) 的灯。例如:1,4,7,10…
一个计数器 c 记录按钮被按下的次数。当宴会开始,所有的灯都亮着,此时计数器 c 为 0。
你将得到计数器 c 上的数值和经过若干操作后某些灯的状态。写一个程序去找出所有灯最后可能的与所给出信息相符的状态,并且没有重复。
输入格式
第一行一个正整数 n;第二行一个整数 c,表示最后计数器的数值。
第三行若干个整数,表示最后亮着的灯,以 -1
结束。
第四行若干个整数,表示最后关着的灯,以 -1
结束。
保证不会有灯会在输入中出现两次。
输出格式
每一行是所有灯可能的最后状态(没有重复)。
每一行有 n 个字符,第 i 个字符表示 i 号灯。0 表示关闭,1 表示亮着。这些行必须从小到大排列(看作是二进制数)。
如果没有可能的状态,则输出一行 IMPOSSIBLE
。
输入输出样例
输入 #1
10 1 -1 7 -1
输出 #1
0000000000 0101010101 0110110110
说明/提示
【数据范围】
对于 100% 的数据,10≤n≤100,0≤c≤104。
【样例解释】
在这个样例中,有三种可能的状态:
-
所有灯都关着
-
1,4,7,10 号灯关着,2,3,5,6,8,9 亮着。
-
1,3,5,7,9 号灯关着,2,4,6,8,10 亮着。
翻译来自NOCOW
USACO 2.2
#include<bits/stdc++.h>
using namespace std;
//每6个灯的状态都是一样的,故只需记录前6盏灯的情况
char lamp[10][10]={
{"111111"}, //按过(1,2,3) 次数:0次,3次
{"011011"}, //按过(1,2,3,4),(4) 次数:4次,1次
{"101010"}, //按过(1,2),(3) 次数:2次,1次
{"010101"}, //按过(2),(1,3) 次数:1次,2次
{"001110"}, //按过(1,2,4),(3,4) 次数:3次,2次
{"110001"}, //按过(1,3,4),(2,4) 次数:3次,2次
{"100100"}, //按过(1,4),(2,3,4) 次数:2次,3次
{"000000"}, //按过(1),(2,3) 次数:1次,2次
};
int num[10][10]={{0,3},{1,4},{1,2},{1,2},{2,3},{2,3},{2,3},{1,2}}; //对应的不同按钮的次数
int lon[10]={0},loff[10]={0};
int n,c,x;
bool judge(int index){
for(int i=0;i<7;++i)
if((lon[i] && lamp[index][i]=='0') || (loff[i] && lamp[index][i]=='1'))
return 0;
return 1;
}
int main(){
scanf("%d%d",&n,&c);
while(1){
scanf("%d",&x);
if(x==-1) break;
lon[(x-1)%6]=1; //存放亮着的灯,直接对6取余保存
}
while(1){
scanf("%d",&x);
if(x==-1) break;
loff[(x-1)%6]=1; //存放灭的灯
}
int cnt=0;
char ans[10][10];
if(c<3){
for(int i=0;i<8;++i) //第i种操作造成的i种状态
for(int j=0;j<=1;++j){ //穷举所有的操作
if((num[i][j]==c || num[i][j]==c-2) && judge(i)) //num[i][j]==c-2成立时,只有有效按钮次数为0
strcpy(ans[cnt++],lamp[i]); //将这种可能性保存起来
}
}
else{
for(int i=0;i<8;++i)
if(judge(i))
strcpy(ans[cnt++],lamp[i]);
}
if(cnt==0) printf("IMPOSSIBLE\n");
else{
for(int i=0;i<cnt-1;++i) //排序
for(int j=0;j<cnt-1-i;++j)
if(strcmp(ans[j],ans[j+1])>0){
char temp[8];
strcpy(temp,ans[j]);
strcpy(ans[j],ans[j+1]);
strcpy(ans[j+1],temp);
}
for(int i=0;i<cnt;++i){
for(int j=0;j<n;++j)
printf("%c",ans[i][j%6]);
printf("\n");
}
}
return 0;
}