[ZJOI2009]硬币游戏
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 920 Solved: 406
[Submit][Status][Discuss]
Description
Orez很喜欢玩游戏,他最近发明了一款硬币游戏。他在桌子的边缘上划分出2*n个位置并按顺时针把它们标号为1,2,……,2n,然后把n个硬币放在标号为奇数的位置上。接下来每次按如下操作:在任意两个硬币之间放上一个硬币,然后将原来的硬币拿走;所放硬币的正反面由它两边的两个硬币决定,若两个硬币均为正面朝上或反面朝上,则所放硬币为正面朝上,否则为反面朝上。 那么操作T次之后桌子边缘上硬币的情况会是怎样的呢?
Input
文件的第一行包含两个整数n和T。 接下的一行包含n个整数,表示最开始桌面边缘的硬币摆放情况,第i个整数ai表示第i个硬币摆放在2*i-1个位置上,ai=1表示正面朝上,ai=2表示反面朝上。
Output
文件仅包含一行,为2n个整数,其中第i个整数bi桌面边缘的第i个位置上硬币的情况,bi=1表示正面朝上,bi=2表示反面朝上,bi=0表示没有硬币。
Sample Input
10 5
2 2 2 1 1 1 1 1 1 2
2 2 2 1 1 1 1 1 1 2
Sample Output
0 1 0 1 0 1 0 1 0 2 0 1 0 2 0 1 0 1 0 1
数据范围
30%的数据 n≤1000 T≤1000
100%的数据 n≤100000 T≤2^60
数据范围
30%的数据 n≤1000 T≤1000
100%的数据 n≤100000 T≤2^60
样例解释
20202010101010101020
01010201010101010201
10102020101010102020
01020102010101020102
20202020201010202020
01010101020102010101
思路
找规律;
题目描述好坑爹,建议看COGS的;
对于某一状态的某一位置,其2k次操作后的情况,与原状态下的左右各k+1的位置的硬币状态有关;
代码实现
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int maxn=2e5+10; 5 int n,m; 6 long long k,l,r; 7 int a[maxn],b[maxn]; 8 int main(){ 9 scanf("%d%lld",&n,&k),m=n<<1; 10 for(int i=1;i<=n;i++) scanf("%d",&b[i*2-1]); 11 while(k){ 12 for(int i=1;i<=n<<1;i++) a[i]=b[i]; 13 int i=0; 14 long long j=1; 15 for(i;j<=k;j<<=1); 16 j>>=1,k-=j; 17 l=1-j,r=1+j; 18 for(int i=1;i<=m;i++){ 19 l=l%m+m,l=l%m,r=r%m; 20 if(!a[l]) b[i]=0; 21 else if(a[l]==a[r]) b[i]=1; 22 else b[i]=2; 23 l++,r++; 24 } 25 } 26 for(int i=1;i<=m;i++){ 27 printf("%d",b[i]); 28 if(i!=m) putchar(' '); 29 else putchar('\n'); 30 } 31 32 return 0; 33 }