HDU 4388 Stone Game II {博弈||找规律}

Stone Game II

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 531    Accepted Submission(s): 300

Problem Description

  Stone Game II comes. It needs two players to play this game. There are some piles of stones on the desk at the beginning. Two players move the stones in turn. At each step of the game the player should do the following operations.
        First, choose a pile of stones. (We assume that the number of stones in this pile is n)
        Second, take some stones from this pile. Assume the number of stones
left in this pile is k. The player must ensure that 0 < k < n and
(k XOR n) < n, otherwise he loses.
        At last, add a new pile of
size (k XOR n). Now the player can add a pile of size ((2*k) XOR n)
instead of (k XOR n) (However, there is only one opportunity for each
player in each game).
The first player who can‘t do these operations
loses. Suppose two players will do their best in the game, you are asked
to write a program to determine who will win the game.

Input

  The
first line contains the number T of test cases (T<=150). The first
line of each test cases contains an integer number n (n<=50),
denoting the number of piles. The following n integers describe the
number of stones in each pile at the beginning of the game.
       You can assume that all the number of stones in each pile will not exceed 100,000.

Output

  For each test case, print the case number and the answer. if the first player will win the game print "Yes"(quotes for clarity) in a single line, otherwise print "No"(quotes for clarity).

Sample Input

3

2

1 2

3

1 2 3

4

1 2 3 3

Sample Output

Case 1: No

Case 2: Yes

Case 3: No

这个题好啊,看了一会没什么思路。看题解发现自己还看错题了。

题目大意:

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

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

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

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

解题思路

把每堆原来a个物品分成两堆,k和k^a,证明得,这样分堆,不会影响二进制中1的总数的奇偶性,(后面会给出证明)为什么要考虑二进制呢?

注意题目中的条件,x^k<x,所以当x的二进制表示中只有一个1时就不能再分了。所以终止条件也有了。

对于操作,因为是乘二,所以并不影响奇偶性结果。

设一堆数目中二进制表示1的个数是m,则所有要操作的步骤就是所有的(m-1)加起来。讨论这个总数的奇偶性就行了。

为何分堆不影响二进制中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.

综上,此题可以解决。

如何统计二进制中1的个数?

可以对2不断取模进行,也可以使用n&(n-1)

后面的证明看博客https://blog.csdn.net/u013243347/article/details/52220551

 1 /**
 2  *          ┏┓    ┏┓
 3  *          ┏┛┗━━━━━━━┛┗━━━┓
 4  *          ┃       ┃  
 5  *          ┃   ━    ┃
 6  *          ┃ >   < ┃
 7  *          ┃       ┃
 8  *          ┃... ⌒ ...  ┃
 9  *          ┃              ┃
10  *          ┗━┓          ┏━┛
11  *          ┃          ┃ Code is far away from bug with the animal protecting          
12  *          ┃          ┃   神兽保佑,代码无bug
13  *          ┃          ┃           
14  *          ┃          ┃        
15  *          ┃          ┃
16  *          ┃          ┃           
17  *          ┃          ┗━━━┓
18  *          ┃              ┣┓
19  *          ┃              ┏┛
20  *          ┗┓┓┏━━━━━━━━┳┓┏┛
21  *           ┃┫┫       ┃┫┫
22  *           ┗┻┛       ┗┻┛
23  */
24 #include<iostream>
25 #include<cstdio>
26 #include<cmath>
27 #include<cstring>
28 #include<algorithm>
29 #include<map>
30 #include<vector>
31 #define mem(a,b) memset(a,b,sizeof(a))
32 #define ll long long
33 #define inf 1000000000
34 #define maxn 1005
35 #define maxm 100005
36 #define eps 1e-10
37 #define for0(i,maxn) for(int i=1;i<=(maxn);++i)
38 #define for1(i,maxn) for(int i=1;i<=(maxn);++i)
39 #define for2(i,x,y) for(int i=(x);i<=(y);++i)
40 #define for3(i,x,y) for(int i=(x);i>=(y);--i)
41 #define mod 1000000007
42 using namespace std;
43 inline int read()
44 {
45     int x=0,f=1;char ch=getchar();
46     while(ch<‘0‘||ch>‘9‘) {if(ch==‘-‘) f=-1;ch=getchar();}
47     while(ch>=‘0‘&&ch<=‘9‘) {x=10*x+ch-‘0‘;ch=getchar();}
48     return x*f;
49 }
50 int getsg(int n)
51 {
52     int count=0;
53     while(n)
54     {
55         n&=(n-1);
56         count++;
57     }
58     return count;
59 }
60 int main()
61 {
62     int T,n;
63     T=read();
64     int index=0;
65     while(T--)
66     {
67         printf("Case %d: ",++index);
68         n=read();
69         int ans=0;
70         for(int i=1;i<=n;++i) ans+=(getsg(read())-1);
71         if(ans&1) puts("Yes");
72         else puts("No");
73     }
74 }

原文地址:https://www.cnblogs.com/TYH-TYH/p/9424933.html

时间: 2024-10-08 22:17:12

HDU 4388 Stone Game II {博弈||找规律}的相关文章

HDU 1564 Play a game (博弈&amp;&amp;找规律)

Play a game Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1430    Accepted Submission(s): 1168 Problem Description New Year is Coming! ailyanlu is very happy today! and he is playing a chessbo

HDU 1517 A Multiplication Game (博弈&amp;&amp;找规律)

A Multiplication Game Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3691    Accepted Submission(s): 2097 Problem Description Stan and Ollie play the game of multiplication by multiplying an in

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的堆,但是这个技能每个人只有一次机会可以使用. 现在问两人轮流操作,都采

HDU 1079 Calendar Game(博弈找规律)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1079 题目大意:给你一个日期(包含年月日),这里我表示成year,month,day,两人轮流操作,每次操作可以将month+1但是,如果下月没有对应的day则只能对day+1(超过该月日数就进入下月一日),或者就day+1.谁最后到达2001.11.4这个日期就是胜者,问先手的人是否能获胜. 解题思路:这个就用上面的P/N分析,一个个月份日期对应的标记上P或N(很快会发现规律只用找每月特定几天),

HDU 2147-kiki&#39;s game(博弈/找规律)

kiki's game Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 40000/10000 K (Java/Others) Total Submission(s): 9174    Accepted Submission(s): 5485 Problem Description Recently kiki has nothing to do. While she is bored, an idea appears in his

HDU 6154 CaoHaha&#39;s staff 思维 找规律

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6154 题目描述: 围成一个面积不小于S的多边形, 最少需要多少根儿线段, 线段可以为单元格边或者对角线 解题思路: 最大的面积肯定是由根号2为边长的正方形围成了, 那么我们把所有正方形都遍历一遍, 找出S介于N, N+1的那个上界N+1设为max, 因为MAX所围成的多边形面积和MAX-1, MAX-2, MAX-3围成的多边形面积, 找出满足条件的最小的一个即可 代码: #include <io

hdu 2147 kiki&#39;s game(找规律)

kiki's game Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 40000/10000 K (Java/Others)Total Submission(s): 10656    Accepted Submission(s): 6455 Problem Description Recently kiki has nothing to do. While she is bored, an idea appears in his

HDU 4349 Xiao Ming&#39;s Hope 找规律

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4349 Xiao Ming's Hope Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1723    Accepted Submission(s): 1144 Problem Description Xiao Ming likes coun

HDU 4588 Count The Carries(找规律,模拟)

题目 大意: 求二进制的a加到b的进位数. 思路: 列出前几个2进制,找规律模拟. #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <stack> #include <vector> using namespace std; int main() { int