Blink(string类+模拟+找循环节)

题目描述:

吊灯由N(3 <= N <= 16)个灯组成,并排成一个圆圈。

在时间T时,他们会操作在时间T-1时左边的灯是开着的灯的灯泡的开关。

他们会在B个单位的时间里一直进行这样的操作( 1 <= B <= 10^15 )

请注意,B可能会超过一般的32位整数的范围。

现在已知每一个灯的初始状态,请计算出在经过B个单位的时间后,每一个灯的状态

输入格式:

第1行是两个整数,N和B

第2~1+N中,第i+1行描述了灯的初始状态,用0(关)与1(开)表示

输出格式:

N行,第i行应输出一个整数,描述灯的最终状态,用0(关)与1(开)表示

输入样例#1:

5 6
1
0
0
0
0

输出样例#1:

1
1
1
0
1

说明 样例输出解释:

下面是样例输出的模拟

Time T=0: 1 0 0 0 0
Time T=1: 1 1 0 0 0
Time T=2: 1 0 1 0 0
Time T=3: 1 1 1 1 0
Time T=4: 1 0 0 0 1
Time T=5: 0 1 0 0 1
Time T=6: 1 1 1 0 1

题解:

一开始就想到去模拟,只是奈何B太大了,但是可以发现存在规律,所以可以用模拟+找循环节ac这题。(B注意用long long)

/*10ms*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ios::sync_with_stdio(false);
    ll N,B,ee,rr;
    char c;
    while(!(cin>>N>>B).eof())
    {
        int y=0;
        string a,b[10000]; ///a存储上一个状态,b存储灯的每次状态
        for(int i=1;i<=N;i++){
            cin>>c;
            if(i<N)
                a.push_back(c); ///将字符c放到string类的a数组最后
            else{
                a.push_back(c); ///将字符c放到string类的a数组最后
                a.insert(a.begin()+0,c); ///因为吊灯是一个圈,所以将a[N]的值插入到a[0]位置
            }
        }
        b[0]=a;	///将a数组复制给b[0]数组
        for(int i=1;i<=B;i++){	
            for(int j=1;j<=N;j++){	///模拟过程
                if(b[i-1][j-1]=='1'){
                    if(b[i-1][j]=='1')a[j]='0';
                    else a[j]='1';
                }
            }
            a[0]=a[N];
            b[i]=a;
            //cout<<b[i]<<endl;
            for(int u=1;u<=i-1;u++){  ///找循环节
                if(b[u]==b[i]){	
                    //printf("u=%d i=%d\n",u,i);
                    ee=u;  ///u为循环节的头,i为循环节的尾
                    y=1;
                    break;	///遇到循环节后打断找寻环节过程
                }
            }
            rr=i;
            if(y)break;  ///遇到循环节后打断模拟过程
        }
        if(rr==B){ ///未遇到循环节,直接输出
             for(int k=1;k<=N;k++){
                    cout<<b[rr][k]<<endl;
                }
        }
        else{	///遇到循环节
            int v=(B-rr)%(rr-ee);
            for(int k=1;k<=N;k++){
                cout<<b[ee+v][k]<<endl;
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值