zoukankan      html  css  js  c++  java
  • hdu 1729 Stone Game 博弈论

    那么对于这题对于每一堆,放石子放满就想当于满的时候取s-c个,反向只是让我理解题意更深。

    首先我们知道(S,S)这个局面是必败局面。对于每一堆能加的数量有限,而当c的值(大于或者等于)

    D=sqrt(s) 或者 D=sqri(s)+1的时候就可以一次完成,就是说可以从当前局面到达(S,S)的局面,

    所以当前局面是必胜局面。而这种情况下,你能造成的局面有集合A={0,1,2,...,s-c-1};因为你可以去

    s-c,s-c-1,s-c-2,.....,1;那么对应mex(x)函数(即A中未出现的最小的一个数字),那么自然该局面的SG值就是s-c了;

    另外当c的值小于D的时候,是不可能一下子加满的,因为c*c+c绝对是小于s的;那么小于D的局面一定能够是必输的吗?很显然不是的。

    对于(S,D-1)这个局面,一定是必输,因为他能到的局面都是必胜!现在c小于D,那么如果(S,C)这个局面能到(S,D);

    就代表这个局面是必胜的。所以现在SG值要在新集合(D,C)中求,而求法与上面的相同求新的D,所以可以用递归函数:当C>D时,返回(S-C)

    差不多就是这样。其实D = sqrt(s);这里算是个加速,要不然就要:while(d*d+d < S) d++;这样会很慢的。

    代码如下:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<iomanip>
     5 #include<cmath>
     6 #include<cstring>
     7 #include<vector>
     8 #define ll __int64
     9 #define pi acos(-1.0)
    10 #define MAX 50000
    11 using namespace std;
    12 int mex(int s,int c)
    13 {
    14     int t=(int)sqrt(1.0*s);
    15     while(t*t+t>=s) t--;
    16     if(t<c) return s-c;
    17     else return mex(t,c);
    18 }
    19 int main(){
    20     int t=0,m,s,c,ans;
    21     while(scanf("%d",&m)&&m){
    22         ans=0;
    23         for(int i=0;i<m;i++){
    24             scanf("%d%d",&s,&c);
    25             if(s==0||c==0||s==c) continue;
    26             ans^=mex(s,c);
    27         }
    28         printf("Case %d:
    ",++t);
    29         puts(ans==0?"No":"Yes");
    30     }
    31     return 0;
    32 }
    View Code

  • 相关阅读:
    B+树的Copy-on-Write设计
    so库链接和运行时选择哪个路径下的库?
    Xapian索引-文档检索过程分析之匹配百分比
    Xapian索引-文档检索过程分析
    Xapian的内存索引-添加文档
    Xapian的内存索引
    Xapian使用入门
    一个std::sort 自定义比较排序函数 crash的分析过程
    编译GCC4.8.2
    使用C++11的一点总结
  • 原文地址:https://www.cnblogs.com/xin-hua/p/3251409.html
Copyright © 2011-2022 走看看