[vijos1554&bzoj1411]硬币游戏<快速幂>

题目链接:https://vijos.org/p/1554

    http://www.lydsy.com/JudgeOnline/problem.php?id=1411

这题真的淫*QAQ。。。

一看题还以为是啥水题,结果啊,是个规律题

我们先来解释一下样例

20202010101010101020   0
01010201010101010201   1
10102020101010102020   2
01020102010101020102   3
20202020201010202020   4
01010101020102010101   5
10101010202020201010   6
01010102010101020101   7
10101020201010202010   8
01010201020102010201   9
10102020202020202020   10
01020101010101010102   11

这后面的数字表示的是第几次操作

然后可以开始找规律了。。。。。。。。。

盯-----------------------------------------------------------------------------------------------------

这个看起来头有点痛,我们优化一波来看

20202010101010101020   0

10102020101010102020   2

20202020201010202020   4

10101010202020201010   6

10101020201010202010   8

10102020202020202020   10

其实我们就可以发现,这个每两次操作,硬币的位置是不会变的,变的只是正反面

然后我们在把这个图继续变换

20202010101010101020   0

10102020101010102020   2

20202020201010202020   4

10101020201010202010   8

我们只留下了2^k次方这些操作

就可以发现,第2^k次方次操作中,第i个数是由最开始的i-2^k和i+2^k这两个数来决定的

所以对于操作次数T

要把T分解成2^k+2^k-1+···+2^1+1这种形式的

其实吧,这就是快速幂

然后快乐的写一个快速幂模板就过了

只是注意一下T是2^60,要用long long存

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdlib>
 6 #include<queue>
 7 #include<cmath>
 8 #define maxn 200005
 9 using namespace std;
10 
11 int n;
12 long long x,d=1;
13 int a[maxn*2],b[maxn*2];
14 
15 int did(int pos,long long dis){
16     int l=((pos-dis)%n+n)%n,r=(pos+dis)%n;
17     //pos-dis有可能<-n; 
18     if(l==0)l=n;if(r==0)r=n;
19     if(a[l]==0)return 0;
20     if(!(a[l]^a[r]))return 1;
21     return 2;
22 }
23 
24 void work(){
25     while(x){
26         if(x&1){
27             for(int i=1;i<=n;i++)
28                 b[i]=did(i,d);
29             for(int i=1;i<=n;i++)
30                 a[i]=b[i];            
31         }
32         x>>=1;d<<=1;
33     }
34 }
35 
36 int main(){
37     scanf("%d%lld",&n,&x);n<<=1;
38     for(int i=1;i<=n;i+=2){
39         scanf("%d",&a[i]);
40     }
41     work();
42     for(int i=1;i<n;i++){
43         printf("%d ",a[i]);
44     }printf("%d",a[n]);
45 } 
View Code

【总结】

然后看见我的注释没,我就在那里卡了很久,因为我最开始的L是(pos-dis+n)%n;

然后光荣爆炸,毕竟,我没算到pos-dis的绝对值可能是小于n的啊

所以那个位置的正确写法((pos-dis)%n+n)%n;

 

posted @ 2017-11-06 17:48  Danzel♂  阅读(207)  评论(0编辑  收藏  举报