bzoj 1411 [ZJOI2009]硬币游戏

【题目链接】

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

【题意】

N个硬币放在一个有2*N个位置的圆桌上,求T次操作后的情况。对于一个操作,如果两边都是正或都是负,则在中间放一个负,否则放一个正。

【思路】

把正设为0,负设为1,则一个硬币的状态为两边硬币的抑或。

把两次操作看作一次,则一次操作后硬币只有状态发生改变而位置不会改变。

  通过数学归纳法得到:一个硬币的状态在操作2^k后是其左右两边与其相距2^k的硬币的抑或。直观的看,就是中间的项都被抑或消掉了。

将T/2进行二进制拆分,不断进行操作即可。最后考虑T的奇偶性。

【代码】

 1 #include<cmath>
 2 #include<queue>
 3 #include<vector>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<iostream>
 7 #include<algorithm>
 8 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 9 using namespace std;
10
11 typedef long long ll;
12 const int N = 5e5+10;
13
14 ll read() {
15     char c=getchar();
16     ll f=1,x=0;
17     while(!isdigit(c)) {
18         if(c==‘-‘) f=-1; c=getchar();
19     }
20     while(isdigit(c))
21         x=x*10+c-‘0‘,c=getchar();
22     return x*f;
23 }
24
25 int n; ll m;
26 int a[N],ans[N];
27
28 int main()
29 {
30     //freopen("in.in","r",stdin);
31     //freopen("out.out","w",stdout);
32     n=read(),m=read();
33     FOR(i,1,n) ans[i]=read(),ans[i]--;
34     ll x=m/2;
35     for(ll p=1;p<=x;p<<=1) if(x&p) {
36         memcpy(a,ans,sizeof(int)*(n+1));
37         ll k=p%n;
38         for(int i=1;i<=n;i++) {
39             ll l=(i-1-k+n)%n+1,r=(i-1+k)%n+1;
40             ans[i]=a[l]^a[r];
41         }
42     }
43     ans[0]=ans[n],ans[n+1]=ans[1];
44     if(m&1) FOR(i,1,n-1) printf("0 %d ",(ans[i]^ans[i+1])+1);
45     else FOR(i,1,n-1) printf("%d 0 ",ans[i]+1);
46     if(m&1) printf("0 %d",(ans[n]^ans[n+1])+1);
47     else printf("%d 0",ans[n]+1);
48     return 0;
49 }

还能再任性点么 =-=

时间: 2024-12-17 04:33:27

bzoj 1411 [ZJOI2009]硬币游戏的相关文章

BZOJ 1411&amp;&amp;Vijos 1544 : [ZJOI2009]硬币游戏【递推,快速幂】

1411: [ZJOI2009]硬币游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 897  Solved: 394[Submit][Status][Discuss] Description Orez很喜欢玩游戏,他最近发明了一款硬币游戏.他在桌子的边缘上划分出2*n个位置并按顺时针把它们标号为1,2,……,2n,然后把n个硬币放在标号为奇数的位置上.接下来每次按如下操作:在任意两个硬币之间放上一个硬币,然后将原来的硬币拿走:所放硬币的正反面

1381 硬币游戏

1381 硬币游戏 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 有一个简单但是很有趣的游戏.在这个游戏中有一个硬币还有一张桌子,这张桌子上有很多平行线(如下图所示).两条相邻平行线之间的距离是1,硬币的半径是R,然后我们来抛硬币到桌子上,抛下之后硬币有时候会和一些直线相交(相切的情况也算是相交),有时候不会. 请你来计算一下抛一次硬币之后,该硬币和直线相交数目的期望. Input 第一行给出一个整数T,表示有T组数据(1<=T<=10000). 第2行到T

bzoj2017[Usaco2009 Nov]硬币游戏*

bzoj2017[Usaco2009 Nov]硬币游戏 题意: 初始时,一个有N枚硬币的堆栈放在地上,每枚硬币都有一个价值.开始玩游戏时,第一个玩家可以从堆顶拿走一枚或两枚硬币.之后每一轮中,当前的玩家至少拿走一枚硬币,至多拿走对手上一次所拿硬币数量的两倍.当没有硬币可拿时,游戏结束. 两个玩家都希望拿到最多钱数的硬币.求第一个玩家最多能拿多少钱.n≤2000. 题解: 首先有dp方程:f[i][j][0]=max(f[i][k][1]+sum(i-k,i)),1≤k≤min(j*2,i),f[

BZOJ 2756 奇怪的游戏(最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2756 题意:在一个 N*M 的棋盘上玩,每个格子有一个数.每次 选择两个相邻的格子,并使这两个数都加上 1. 问最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同一个数则输出-1. 思路:对棋盘进行黑白染色,则每次操作使得黑白两色的格子总和各增加1.设黑色总和s1,个数cnt1:白色总和s2,个数cnt2,设最后的数字为x,那么有: x*cnt1-s1=x*cnt2-s2. (

HDU 3537 Mock Turtles型翻硬币游戏

题目大意: 每次可以翻1个或者2个或者3个硬币,但要保证最右边的那个硬币是正面的,直到不能操作为输,这题目还有说因为主人公感情混乱可能描述不清会有重复的硬币说出,所以要去重 这是一个Mock Turtles型翻硬币游戏 下面是对这个类型游戏的讲解 约束条件6:每次可以翻动一个.二个或三个硬币.(Mock Turtles游戏) 初始编号从0开始. 当N==1时,硬币为:正,先手必胜,所以sg[0]=1. 当N==2时,硬币为:反正,先手必赢,先手操作后可能为:反反或正反,方案数为2,所以sg[1]

BZOJ 1413 取石子游戏(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1413 题意:n堆石子排成一排.每次只能在两侧的两堆中选择一堆拿.至少拿一个.谁不能操作谁输. 思路:参考这里. int f1[N][N],f2[N][N],n,a[N]; void deal() { RD(n); int i,j,k; FOR1(i,n) RD(a[i]),f1[i][i]=f2[i][i]=a[i]; int p,q,x; for(k=2;k<=n;k++) for(

51Nod - 1381 硬币游戏

51Nod - 1381 硬币游戏 有一个简单但是很有趣的游戏.在这个游戏中有一个硬币还有一张桌子,这张桌子上有很多平行线(如下图所示).两条相邻平行线之间的距离是1,硬币的半径是R,然后我们来抛硬币到桌子上,抛下之后硬币有时候会和一些直线相交(相切的情况也算是相交),有时候不会. 请你来计算一下抛一次硬币之后,该硬币和直线相交数目的期望. Input 第一行给出一个整数T,表示有T组数据(1<=T<=10000). 第2行到T+1,每行给出一个整数R.(0< R <= 10,00

BZOJ 1978 取数游戏(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1978 题意:给出一个数列a,在其中找出下标依次增大的数,使得任意相邻的两个数的最大公约数大于等于m.找出最多的数字. 思路:f[i]表示前面的数字中最大公约数为i可以找出的最多的数字个数.那么对于当前数字x: 接着更新f: int f[N],a[N]; int n,m; int main() { RD(n,m); int i; FOR1(i,n) RD(a[i]); int j,k;

1289 大鱼吃小鱼 1305 Pairwise Sum and Divide 1344 走格子 1347 旋转字符串 1381 硬币游戏

1289 大鱼吃小鱼 有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右.游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼.从左到右给出每条鱼的大小和游动的方向(0表示向左,1表示向右).问足够长的时间之后,能剩下多少条鱼? Input 第1行:1个数N,表示鱼的数量(1 <= N <= 100000). 第2 - N + 1行:每行两个数A[i], B[i],中间用空格分隔,分别表示鱼的大小及游动的方向(1 <= A[i] <= 10^9,B[i] = 0 或 1