zoukankan      html  css  js  c++  java
  • HDU 1729 Stone Game 石头游戏 (Nim, sg函数)

    题意:

      有n个盒子,每个盒子可以放一定量的石头,盒子中可能已经有了部分石头。假设石头无限,每次可以往任意一个盒子中放石头,可以加的数量不得超过该盒中已有石头数量的平方k^2,即至少放1个,至多放k^2个。

    思路:

      跟常规nim的区别就是加了个限制“每次加的量不超平方”。盒子容量上限是100万,那么就不能直接计算SG了,会超时。sg打表后找规律。根据剩下多少个空位来决定sg值。都是0123456这样子递增的,碰到不能一次加满就变为0,然后继续递增,一直这样。

      我的方案是,对于每个盒子大小,找到除了自己之外的第一个P状态,记录下来。根据给定的s和c来查表,找到大于c且离c最近的一个p点,然后用该点减去c就是sg值了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 using namespace std;
     5 const int N=1001000;
     6 int p[N];//p[i]表示的值经过一次不能到达i,但是经过2次必定可以到达i,也就是说i是一个P点,p[i]是上一个P点
     7 void cal()
     8 {
     9     //p[1]之前无必败点,只有(1,0)这一个必胜点,要特殊处理
    10     int k=1;
    11     while(k+k*k<N)
    12     {
    13         int q=k+k*k+1;
    14         int up=k+1+(k+1)*(k+1);
    15         for(int i=q; i<=min(up,N-1); i++)    p[i]=k;
    16         k++;
    17     }
    18 }
    19 int get_sg(int s,int c)
    20 {
    21     int tmp=s;
    22     while(s&&s>=c)
    23     {
    24         tmp=s;
    25         s=p[s];
    26     }
    27     if(tmp==1)    return 1;   //对付(1,0)的情况
    28     return (tmp-c);
    29 }
    30 
    31 int main()
    32 {
    33     cal();//预处理
    34     //freopen("input.txt","r",stdin);
    35     int n, j=0,ans,s,c;
    36     while(scanf("%d",&n), n)
    37     {
    38         ans=0;
    39         while(n--)
    40         {
    41             scanf("%d%d",&s,&c);
    42             if(s&&c)    ans^=get_sg(s,c);
    43         }
    44         if(ans)    printf("Case %d:
    Yes
    ",++j);
    45         else    printf("Case %d:
    No
    ",++j);
    46 
    47     }
    48 
    49     return 0;
    50 }
    AC代码
  • 相关阅读:
    VMware Workstation-虚拟机的安装
    Linux操作系统-命令-free
    Linux操作系统-命令-vmstat
    抛出一个异常
    字符集
    页面缓存
    表单域
    弹出式说明
    canselBubble 和 stopPropagation理解
    JS---递归函数理解
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4517955.html
Copyright © 2011-2022 走看看