• codeforces 88E Interesting Game


    题目大意:

    两个好朋友再将一堆物品分堆,每次都将一堆物品分成数量连续的至少两个堆,直到一个人不能分堆为输

    第一次做博弈问题,看了百度文库的http://wenku.baidu.com/link?url=C6qxEhqBEJJFDPC2nSW8kaOer2s_WyOxAhUi0QzF_-B38Gw7KqbbjFvuiaLUvuoGYtliZE_JAH_PO1VPpOT1Vo5OvbyPzBR3Q5IlmWYIHuy

    感觉讲的还是蛮好的

    这里因为每次至少要分两个堆

    所以初始sg[0] = sg[1] = sg[2] = 0 ,为 P 态(必胜态)

    假设某堆物品n可以分成a , a+1 , a+2 , a+3 ... a+k-1 这样k堆

    根据等差数列方程可得 (2*a+k-1)*k = 2*n

    那么我们就可以找所有 可作为 2*n的因子的k , 这里因为a>=1 ,所以(2*a+k-1)>k的,所以只要找2~sqrt(2*n+0.5)中符合的k的因子就好了,然后判断里面的a是否存在

    如果都成立说明这是一种分的方式,这就是一个n的可到达点,记录当前的点sg值已访问过,当前点的sg值是由这个点中所有堆的异或值得到

    我们这里异或过程中不断记录异或的前缀和减少计算过程

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <cmath>
     5 using namespace std;
     6 const int N = 100010;
     7 
     8 int sg[N] , sum[N] , minn[N] , vis[N];
     9 
    10 void init_sg()
    11 {
    12     sg[0] = sg[1] = sg[2] = 0;
    13     sum[0] = sum[1] = sum[2] = 0;
    14     memset(minn , 0x3f , sizeof(minn));
    15     for(int n=3 ; n<=100000 ; n++){
    16         int t = 2*n;
    17         int factor = (int)(sqrt(t+0.5));
    18         for(int k=2 ; k<=factor ; k++){
    19             if(t % k == 0 && t/k+1-k>0 && !((t/k+1-k)&1)){
    20                 int a = (t/k+1-k)/2;
    21                 int p = sum[a+k-1]^sum[a-1];
    22                 vis[p] = n;
    23                 if(p == 0) minn[n] = min(minn[n] , k);
    24             }
    25         }
    26         //找没有出现过的最小的sg函数
    27         int v = 0;
    28         while(1){
    29             if(vis[v] != n){
    30                 sg[n] = v;
    31                 break;
    32             }
    33             v++;
    34         }
    35         //记录当前的sum[]前缀
    36         sum[n] = sum[n-1]^sg[n];
    37     }
    38 }
    39 
    40 int main()
    41 {
    42   //  freopen("a.in" , "r" , stdin);
    43     init_sg();
    44     int n;
    45     while(scanf("%d" , &n) == 1)
    46     {
    47         if(!sg[n]){
    48             puts("-1");
    49             continue;
    50         }
    51         printf("%d
    " , minn[n]);
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    Pwn-warmup_csaw_2016 writeup
    操作系统习题总结
    操作系统-存储器管理部分(待更新)
    树与二叉树之间的互相转换
    黑客攻防技术宝典-反病毒篇笔记(三)
    jaegeropentracing的Java-client完整分布式追踪链
    jaegeropentracing的Java-client
    IDEA2018.2版本注册
    Spring整合CXF webservice restful 实例
    带有WS-Security验证的webservice
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4246643.html
Copyright © 2020-2023  润新知