zoukankan      html  css  js  c++  java
  • hdu 4388 Stone Game II

    Stone Game II

     HDU - 4388 

    题目大意:

    给出n堆物品,每堆物品都有若干件,现在A和B进行游戏,每人每轮操作一次,按照如下规则:

    1. 任意选择一个堆,假设该堆有x个物品,从中选择k个,要保证0<k<x且0<(x^k)<k。

    2. 再增加一个大小为x^k的堆(也就相当于将一个x个物品的堆变成一个k个物品的堆和一个x^k个物品的堆),另外有一个技能,可以将这个大小为x^k的堆变成(2*k)^x的堆,但是这个技能每个人只有一次机会可以使用。

    现在问两人轮流操作,都采取最优策略,最后不能操作的人输,问谁会赢。

    /*
        先不考虑技能,其实每轮的操作就是将一个大小为x的堆分成大小为k和(x^k)的堆,这里很关键的一点是要能发现分堆之前x中二进制1的个数与分堆之后k与(x^k)的二进制1个数和的奇偶性是相同的。这个结论可以这样想,考虑x的某一位p,分四种情况:
        1. 如果x的第p位为1且k的第p位也为1,那么(x^k)的第p位就是0.
        2. 如果x的第p位为1且k的第p位也为0,那么(x^k)的第p位就是1.
        3. 如果x的第p位为0且k的第p位也为1,那么(x^k)的第p位就是1.
        4. 如果x的第p位为0且k的第p位也为0,那么(x^k)的第p位就是0.
        可以发现无论哪种情况,奇偶性都不会发生变化,这是本题的关键。
        另外考虑游戏怎么终止,很显然当一个堆x的二进制1的个数只有1个的时候,就不能再分了,那么如果所有的堆都这样,游戏就终止了,关键看从开始到终止需要奇数步还是偶数步就能判断输赢。
        假设这些堆最后会分成y个堆,那么一共就分了y-n次,每个堆大小的二进制1个数都是1,这样二进制1的总是就是y,而y和x二进制1的个数z已经证明奇偶性相同,所以y-n和z-n奇偶性就是相同的,所以我们只需要判断z-n的奇偶性,这题就解决了,非常巧妙。
    */
    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,T;
    int count(int x){
        int res=0;
        while(x){
            res+=x&1;
            x>>=1;
        }
        return res;
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%d",&T);
        for(int c=1;c<=T;c++){
            printf("Case %d: ",c);
            scanf("%d",&n);
            int cnt=0,x;
            for(int i=1;i<=n;i++){
                scanf("%d",&x);
                cnt+=count(x);
            }
            cnt-=n;
            if(cnt&1)puts("Yes");
            else puts("No");
        }
        return 0;
    }
  • 相关阅读:
    将博客搬至CSDN
    JDBC
    Java刷题常用API
    Java的反射机制
    Java的IO流
    Docker原理:Cgroup
    Docker原理:Namespace
    Anaconda软件安装使用问题
    初步了解Unix系统的I/O模式
    深入理解索引和AVL树、B-树、B+树的关系
  • 原文地址:https://www.cnblogs.com/thmyl/p/8135700.html
Copyright © 2011-2022 走看看