【USACO2-2-4】派对灯

原题

首先,每个按键按两下和没按是一个样子。所以每个按键有只有两种情况,按了和没按。最后总的不同的情况就是2^4=16种。

然后我们发现按下1和2与按下3是一样的,进而发现12=3,23=1,13=2。非常奇妙对吧!接下来所有的情况就只剩下

1,2,3,4     14,24,34    不按八种情况

当c=0时 只有不按

当c=1时 只有1,2,3,4

当c=2时 只有不按,14,24,34,1,2,3七种情况

当c=3时 八种情况都可以

当一个偶数n>=2的时候,它可以被分解为n=2*p+3*q的形式(p,q属于正整数)。当这数为奇数时,成立。当n为奇数时,n-3一定为偶数,所以n>=3时成立。因此可知道所有的n>=2的正整数都可以被分为n=2*a+3*b+3的形式

也就是说,当c>4时都化为c=3的情况。(可能需要时间理解一下了,我尽力了qwq)

对于程序实现就是读入的时候把必须亮着/关上的灯进行标记。预处理出上文说的八种情况,再根据字典序逐个判断就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int ans[10][6]=
{
    {1,1,1,1,1,1},//0 
    {0,0,0,0,0,0},//1      
    {0,1,0,1,0,1},//2     
    {1,0,1,0,1,0},//3      
    {0,1,1,0,1,1},//4      
    {1,0,0,1,0,0},//1,4    
    {1,1,0,0,0,1},//2,4   
    {0,0,1,1,1,0},//3,4    

};
int up[10100],off[10100];
int n,c,sign=1;

void judge(int x)
{
    bool f=true;
    for (int i=0;i<6;i++)
        if ((up[i]&&!ans[x][i])||(off[i]&&ans[x][i])) f=false;
    if (f)
    {
        sign=0;
        for (int i=0;i<n;i++) printf("%d",ans[x][i%6]);
        printf("\n");
    }

}


int main()
{
    int o;	
    scanf("%d%d",&n,&c);
    while(~scanf("%d",&o)&&o!=-1) up[(o-1)%6]=1;
    while(~scanf("%d",&o)&&o!=-1) off[(o-1)%6]=1;
    if (c>=4) c=3;
    switch(c)
    {
        case 0:{judge(0);break;}
        case 1:
        {
            judge(1);
            judge(2);
            judge(4);
            judge(3);
            break;
        }
        case 2:
        {
            judge(1);
            judge(7);
            judge(2);
            judge(5);
            judge(3);
            judge(6);
            judge(0);
            break;
        }
        case 3:
        {
            judge(1);
            judge(7);
            judge(2);
            judge(4);
            judge(5);
            judge(3);
            judge(6);
            judge(0);
            break;
        }
    }
    if (sign) printf("IMPOSSIBLE\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值