zoukankan      html  css  js  c++  java
  • 又见博弈

    CF73中的Div2的E题,Interesting Game,题目是这样的,可以对一堆石头分成a1,a2,a3…,an这n堆,第i堆有ai颗石头,并满足ai = ai-1 + 1,两个人轮流操作,直到一方不能做这样的操作的话,他就输了。

    要想使用SG那个异或定理的话,就要用SG函数的定义,根据SG函数的定义求出SG函数的值。

    然后这题就是对没种情况进行枚举,求出每个状态的SG值,并记录下如果赢的话,最少要弄几堆,代码如下:

    #include <iostream>
    #include <string>
    using namespace std;
     
    const int MAX = 1e5 + 5;
     
    int dp[MAX], sum[MAX], tmp[MAX];
    int m_min[MAX];
     
    void ready()
    {
        memset(dp, 0, sizeof(dp));
        memset(tmp, 0, sizeof(tmp));
        memset(m_min, 0, sizeof(m_min));
        sum[0] = sum[1] = sum[2] = 0;
        int ans = 0;
        for(int i = 3; i < MAX; i++)
        {
            for(int j = 2; ; j++)
            {
                if((j + 1) * j / 2 > i)  break;
                int left = i - (j + 1) * j / 2;
                if(left % j)  continue;
                int x = left / j;
                //dp[1 + x]^...^dp[j + x] = sum[j + x] ^ sum[x]
                tmp[sum[j + x] ^ sum[x]] = i;
                if(m_min[i] == 0 && (sum[j + x] ^ sum[x]) == 0)  m_min[i] = j;
            }
     
            while(tmp[dp[i]] == i)  dp[i]++;
            
            sum[i] = sum[i - 1] ^ dp[i];
        }
    }
     
    int main()
    {
        ready();
        int n;
        scanf("%d", &n);
        if(dp[n] == 0)  printf("-1");
        else  printf("%d", m_min[n]);
    }

    然后这的话,就可以用同样的方法做出来了。

    ZOJ1083这题是道经典问题,题意是对一条线段进行染色,每次只能然一段长度为2单位的线,谁不能染的话,就输掉,也是要求出SG函数。就是利用到可以把一个游戏拆成几个子游戏的这个特点。

    #include <iostream>
    #include <string>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    using namespace std;
     
    const int MAX = 100;
     
    int dp[MAX], tmp[MAX];
     
    void ready()
    {
        memset(dp, 0, sizeof(dp));
        memset(tmp, 0, sizeof(tmp));
        
        for(int i = 2; i < MAX; i++)
        {
            for(int j = 0; j < i - 1; j++)
                tmp[dp[j] ^ dp[i - j - 2]] = i;
     
            while(tmp[dp[i]] == i)  dp[i]++;
        }
    }
     
    int main()
    {
        ready();
        int n;
        while(scanf("%d", &n) != EOF)
        {
            int ans = 0;
            for(int i = 0; i < n; i++)
            {
                int t;
                scanf("%d", &t);
                ans ^= dp[t];
            }
            puts(ans == 0 ? "No" : "Yes");
        }
    }
  • 相关阅读:
    时间那点儿事儿 -- 时间戳,时区,冬令时,夏令时
    iOS: 并发编程的几个知识点
    iOS: 聊聊 Designated Initializer(指定初始化函数)
    iOS 滑动性能优化
    iPad 多任务 Spilt View & Size Class
    iOS: 如何正确的绘制1像素的线
    iOS: Crash文件解析(一)
    iOS:使用MVC模式帮ViewController瘦身
    iOS:项目中疑难Crash问题集锦
    最近面试人的一点儿感受
  • 原文地址:https://www.cnblogs.com/litstrong/p/2084846.html
Copyright © 2011-2022 走看看