Vijos 1554题:硬币游戏

描述

Orez很喜欢玩游戏,他最近发明了一款硬币游戏。他在桌子的边缘上划分出2*n个位置并按顺时针把它们标号为1,2,……,2n,然后把n个硬币放在标号为奇数的位置上。接下来每次按如下操作:在任意两个硬币之间放上一个硬币,然后将原来的硬币拿走;所放硬币的正反面由它两边的两个硬币决定,若两个硬币均为正面朝上或反面朝上,则所放硬币为正面朝上,否则为反面朝上。
那么操作T次之后桌子边缘上硬币的情况会是怎样的呢?

格式

输入格式

输入第一行包含两个整数n和T。
接下的一行包含n个整数,表示最开始桌面边缘的硬币摆放情况,第i个整数ai表示第i个硬币摆放在2*i-1个位置上,ai=1表示正面朝上,ai=2表示反面朝上。

输出格式

输出仅包含一行,为2n个整数,其中第i个整数bi桌面边缘的第i个位置上硬币的情况,bi=1表示正面朝上,bi=2表示反面朝上,bi=0表示没有硬币。

样例1

样例输入1

10 5
2 2 2 1 1 1 1 1 1 2

样例输出1

0 1 0 1 0 1 0 1 0 2 0 1 0 2 0 1 0 1 0 1

限制

每点1s。

提示

30%的数据 n≤1000 T≤1000
100%的数据 n≤100000 T≤2^60

来源

NOI2009浙江省省选第二题


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

const int MAXN = 200003;
int a[MAXN], b[MAXN];
long long n, T, m;
long long l, r;
int work(long long x, long long y) {
    l = (x - y) % m + m;
    l = l % m;
    r = (x + y) % m;
    if(a[l] == 0) return 0;
    if(a[l] == a[r]) return 1;
    return 2;
}

void solve(long long k, long long c) {
    if(!k) return;
    solve(k / 2, c << 1);
    if(!(k % 2)) return;
    for(int i = 1; i <= (int)m; i++) b[i] = work((long long)i, c);
    swap(a, b);
}

int main() {
    cin>>n>>T;
    m = n << 1;
    for(int i = 1; i <= (int)n; i++) cin>>a[i * 2 - 1];
    solve(T, 1);
    for(int i = 1; i <= (int)m; i++) {
        cout<<a[i];
        if(i != m) putchar(' ');
        else putchar('\n');
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值