题目描述:
吊灯由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;
}