巨魔没金币

69 篇文章 0 订阅

巨魔没金币


题目描述

某巨魔去了一趟拍卖行卖东西,赚了不少金币,然后又买了些东西,就没金币了。
该巨魔没了金币,但他还有很多银币。
他搞了张圆桌。划分出 2N 个位置标号 1 2N,然后把 N 个银币放在奇数位置上。
接下来每次按如下操作:在任意两个银币之间放上一个银币,然后将原来的银币拿走;
所放银币的正反面由它两边的两个银币决定,若两个银币均为正面朝上或反面朝上,则所放银币为正面朝上,否则为反面朝上。
那么操作 T 次之后桌子边缘上银币的情况会是怎样的呢?


输入格式

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


输出格式

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


样例输入

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


样例输出

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


数据范围

30% 的数据: 1N1000 1T1000
100% 的数据: 1N100000 1T260


Solution

若将每一位上的数字减 1 ,则可知一次操作对应两个数字求异或。
打表发现,进行 2k 次操作后, i 位上的数字为 i2k i+2k 上的数字的异或值(将 n 个数字向左、右无限复制)。
那么,我们可以将 T 分解为 2 的幂之和,然后逐步求出答案。


Summary

考场上我是发现了

进行 2k 次操作后, i 位上的数字为 i2k i+2k 上的数字的异或值(将 n 个数字向左、右无限复制)

的规律的。

但当时特别脑残,认为这个规律只能做一个特判,即 T 2 <script type="math/tex" id="MathJax-Element-831">2</script> 的幂的情况……然后就弃疗了。


Code

#include <iostream>
#include <cstdio>

#define LL long long

using namespace std;

LL n,t;
LL w[200010];
LL tot[200010];

void work(LL x){
    LL tmp=1;
    while(tmp<=x)tmp<<=1;
    tmp>>=1;
    while(x){
        while(tmp>x)tmp>>=1;
        for(int i=1;i<=2*n;i++){tot[i]=w[i];w[i]=-1;}
        if(tot[1]!=-1&&tmp==1||tot[1]==-1&&tmp!=1)
            for(int i=2;i<=2*n;i+=2){
                w[i]=tot[(((i-tmp)-1)%(2*n)+2*n)%(2*n)+1]^tot[((i+tmp)-1)%(2*n)+1];
            }
        else
            for(int i=1;i<=2*n;i+=2){
                w[i]=tot[(((i-tmp)-1)%(2*n)+2*n)%(2*n)+1]^tot[(((i+tmp)-1)%(2*n)+2*n)%(2*n)+1];
            }
        x-=tmp;
    }
}

int main(){

    freopen("silver.in","r",stdin);
    freopen("silver.out","w",stdout);

    scanf("%lld%lld",&n,&t);
    for(int i=1;i<=n;i++){
        w[2*i]=-1;
        scanf("%lld",&w[2*i-1]);
        w[2*i-1]--;
    }
    work(t);
    for(int i=1;i<=2*n;i++)printf("%d ",w[i]+1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值