• hdu 3537 翻硬币 每次能翻1个 或2个 或3个


    N 枚硬币排成一排,有的正面朝上,有的反面朝上。我们从左开始对硬币按1 到N 编号。

    第一,游戏者根据某些约束翻硬币,但他所翻动的硬币中,最右边那个硬币的必须是从正面翻到反面。

    第二,谁不能翻谁输。

    有这样的结论:局面的SG 值为局面中每个正面朝上的棋子单一存在时的SG 值的异或和。即一个有k个硬币朝上,朝上硬币位置分布在的翻硬币游戏中,SG值是等于k个独立的开始时只有一个硬币朝上的翻硬币游戏的SG值异或和。比如THHTTH这个游戏中,2号、3号、6号位是朝上的,它等价于TH、TTH、TTTTTH三个游戏和,即sg[THHTTH]=sg[TH]^sg[TTH]^sg[TTTTTH].我们的重点就可以放在单个硬币朝上时的SG值的求法。

    这一题是每次可以翻动一个、二个或三个硬币。

    初始编号从0开始。如果先手胜则输出NO
    sg[i] 表示 第i个位置上为正 其余位置为反面

    只有一枚硬币时 正,先手必胜,则它的后继状态的sg值为0 所以sg[0]=1.
    有2枚硬币时 反正 翻2个 后继状态为sg[0] 翻1个 后继状态为 所以sg[1] = 2
    ....


    Sample Input
    0
    1 //n
    0 //正面朝上硬币的位置
    4
    0 1 2 3

    Sample Output
    Yes
    No
    Yes

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 # include <algorithm>
     5 # include <string>
     6 # include <cmath>
     7 # include <queue>
     8 # include <list>
     9 # define LL long long
    10 using namespace std ;
    11 
    12 int a[110];
    13 
    14 int SG(int x)
    15 {
    16     int tmp = x;
    17     int cnt = 0;
    18     while(tmp)
    19     {
    20         if(tmp&1)cnt++;
    21         tmp>>=1;
    22     }
    23     if(cnt&1)return 2*x;
    24     else return 2*x + 1;
    25 }
    26 
    27 int main()
    28 {
    29     int n;
    30     while(scanf("%d",&n)==1)
    31     {
    32         for(int i = 0;i < n;i++)
    33             scanf("%d",&a[i]);
    34         sort(a,a+n);
    35         n = unique(a,a+n)-a;
    36         int sum = 0;
    37         for(int i = 0;i < n;i++)
    38             sum ^= SG(a[i]);
    39         if(sum)printf("No
    ");
    40         else printf("Yes
    ");
    41     }
    42     return 0;
    43 
    44 }
    View Code

    打表 找规律
    发现 1 2 4 7 8.... 这些的sg值为本身的两倍 这些数字的二进制只含有奇数个1 剩余的sg值为本身的2倍+1 (比如0 3 5 6 9这些)

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 # include <algorithm>
     5 # include <string>
     6 # include <cmath>
     7 # include <queue>
     8 # include <list>
     9 # define LL long long
    10 using namespace std ;
    11 
    12 int sg[1010];
    13 bool vis[1010];
    14 
    15 int mex(int n) //求N的SG值
    16 {
    17     if(sg[n] != -1)return sg[n];
    18     memset(vis,false,sizeof(vis));
    19     vis[0] = 1 ; //只有1枚硬币,后继必败
    20     int i , j  ;
    21     for (i = 0 ; i < n ; i++)
    22         vis[mex(i)] = 1 ;
    23     for (i = 0 ; i < n ; i++)
    24         for (j = 0 ; j < i ; j++)
    25             vis[mex(i)^mex(j)] = 1 ;
    26     for(i = 0;;i++)
    27         if(vis[i] == false)
    28         {
    29             sg[n] = i;
    30             break;
    31         }
    32     return sg[n];
    33 }
    34 
    35 int main()
    36 {
    37 
    38     memset(sg,-1,sizeof(sg));
    39     sg[0] = 1 ;
    40     for(int i = 1;i <= 200;i++)
    41         sg[i] = mex(i);
    42 
    43     cout<<sg[0]<<" ";
    44        for(int i=1;i<=100;i++)
    45        {
    46           cout<<sg[i]<<" ";
    47           if(i%10==0)
    48             cout<<endl;
    49        }
    50 
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    js返回到顶部
    css培训一
    css常用hack技巧
    css培训二
    css样式渲染规则
    html语义(一)
    css样式表管理
    html+css培训方案
    继承
    封装
  • 原文地址:https://www.cnblogs.com/mengchunchen/p/4844936.html
Copyright © 2020-2023  润新知