zoukankan      html  css  js  c++  java
  • HDU 5795 A Simple Nim (博弈) ---2016杭电多校联合第六场

    A Simple Nim

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 79    Accepted Submission(s): 48


    Problem Description
    Two players take turns picking candies from n heaps,the player who picks the last one will win the game.On each turn they can pick any number of candies which come from the same heap(picking no candy is not allowed).To make the game more interesting,players can separate one heap into three smaller heaps(no empty heaps)instead of the picking operation.Please find out which player will win the game if each of them never make mistakes.
     

     

    Input
    Intput contains multiple test cases. The first line is an integer 1T100, the number of test cases. Each case begins with an integer n, indicating the number of the heaps, the next line contains N integers s[0],s[1],....,s[n1], representing heaps with s[0],s[1],...,s[n1] objects respectively.(1n106,1s[i]109)
     

     

    Output
    For each test case,output a line whick contains either"First player wins."or"Second player wins".
     

     

    Sample Input
    2 2 4 4 3 1 2 4
     

     

    Sample Output
    Second player wins. First player wins.
     

     

    Author
    UESTC
     

     

    Source
     

     

    Recommend
    wange2014
    题意:给定n堆石子,每次有两种操作,1是从任意一堆中取任意个,2是把一堆分为三堆且这三堆都不为空,问谁能赢。
    题解:首先看题目的数据范围是1e9,那么算出每个sg肯定会超时,所以我们想到打表找规律。首先我们暴力打表算出200以内的sg函数值,对于一堆石子来说处理出他的所有后继情况。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int sg[10005]= {0};
    bool vis[10005];
    int t,cas=1;
    void get()
    {
        memset(sg,0,sizeof(sg));
        sg[0]=0;
        for(int i=1; i<=200; i++)
        {
            memset(vis,0,sizeof(vis));
            for(int j=1;j<=i;j++)
            {
                for(int k=1;j+k<=i;k++)
                {
                    if(j!=0&&k!=0&&((i-j-k)!=0))
                    vis[sg[j]^sg[k]^sg[i-j-k]]=1;//操作1
                }
            }
            for(int j=0;j<i;j++)//操作2
            vis[sg[j]]=1;
            for(int x=0; ; x++)
                if(!vis[x])
                    {
                        sg[i]=x;
                        break;
                    }
        }
    }
    int main()
    {
        get();
        for(int i=1;i<=100;i++)
        printf("i: %d    %d
    ",i,sg[i]);
        return 0;
    }

    运行该代码,我们会得到如下结果:

    注意在这个表当中

    观察结果我们可以得知,当n为8的倍数时,sg(n)=n+1; 当(n+1)为8的倍数时,sg(n)=n-1; 否则sg(n)=n;

    所以我们把sg值异或起来就能判断出谁赢了。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            long long x,ans=0;
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                scanf("%lld",&x);
                if(x%8==0)
                ans=ans^(x-1);
                else if((x+1)%8==0)
                ans=ans^(x+1);
                else
                ans=ans^x;
            }
            if(ans)
            puts("First player wins.");
            else
            puts("Second player wins.");
        }
        return 0;
    }
  • 相关阅读:
    git上刚下载的项目就显示有改动
    Windows Server 2012 R2安装Oracle 11g问题
    maven项目更换本地仓库
    dom4j创建和解析xml文档
    java倒计时三种简单实现方式
    JS倒计时两种种实现方式
    java加载properties文件的六中基本方式实现
    MYSQL 高级语法
    MYSQL 基础语法
    Sql 代码规范说明
  • 原文地址:https://www.cnblogs.com/Ritchie/p/5737929.html
Copyright © 2011-2022 走看看