Game (HDU-3389)(博弈+找规律)

Bob and Alice are playing a new game. There are n boxes which have been numbered from 1 to n. Each box is either empty or contains several cards. Bob and Alice move the cards in turn. In each turn the corresponding player should choose a non-empty box A and choose another box B that B<A && (A+B)%2=1 && (A+B)%3=0. Then, take an arbitrary number (but not zero) of cards from box A to box B. The last one who can do a legal move wins. Alice is the first player. Please predict who will win the game.

Input

The first line contains an integer T (T<=100) indicating the number of test cases. The first line of each test case contains an integer n (1<=n<=10000). The second line has n integers which will not be bigger than 100. The i-th integer indicates the number of cards in the i-th box.

Output

For each test case, print the case number and the winner's name in a single line. Follow the format of the sample output.

Sample Input

2
2
1 2
7
1 3 3 2 2 1 2

Sample Output

Case 1: Alice
Case 2: Bob

借鉴一下大佬的思路。

题意:1-N带编号的盒子,当编号满足A>B && A非空 && (A + B) % 3 == 0 && (A + B) % 2 == 1则可以从A中取任意卡片到B中,谁不能取了谁就输。

思路: 
设n=a+b,则当n为3,9,15,21………的时候满足条件,即n为%6=3的数

则有 
((n%6=1)+(n%6=2))%6=(n%6=3) 
((n%6=4)+(n%6=5))%6=(n%6=3) 
((n%6=3)+(n%6=0))%6=(n%6=3)

说明可以从(n%6=2)->(n%6=1)传递卡片 
同理(n%6=5)->(n%6=4),(n%6=0)->(n%6=3)

且1,3,4为这三种情况的终态,即不能转移到其他状态,其他每个状态皆可转移,如 2->1 , 5->4,6->3,7->2,8->1,9->6…..

我们可以它分成一个二分图, 
如果可以从A拿卡片到B,连一条从A到B的边。把编号满足(x%6=1||x%6=3||x%6=4)的放在左边,其他的放在右边。不难发现 
1)只有从左边到右边的边或从右到左的边。 
2)从左边到终态的步数都是偶数步,右边到终态的步数都是奇数步

则有,所有卡片都在偶数步盒子中是必败状态。

因为不论先手将偶数步的盒子中的卡片移走了多少,后手一定可以把这些卡片再往前移动一个盒子,直到移到1 3 4中去为止。

对于只有一个盒子有卡片,而且这个盒子是奇数步盒子来说,先手必胜。

很简单,根据上面的结论,只要先手把这个奇数步盒子中所有卡片全部往下移一个盒子就好了。这样就转移到了先手必败状态。

整个游戏可以看做若干个子游戏的和游戏,偶数步盒子不予考虑,只考虑奇数步盒子中的卡片,这就相当于一个n堆石子的Nim游戏。

在一个奇数步盒子中移走k张卡片,相当于在某一堆石子中取走k个石子。把所有石子取完相当于,所有的卡片都在偶数步的盒子里面,而我们已经证明完这种状态是必败状态了。

所以在代码中就只需要将奇数步盒子中的卡片数异或一下求个Nim和,就能判断胜负了。

AC代码:(Java)

import java.util.*;
public class Main {
	public static void main(String[] args) {
		Scanner in =new Scanner(System.in);
		int t=in.nextInt();
		int k=1;
		while(in.hasNext())
		{
			int sum=0;
		   int	n=in.nextInt();
		   for(int i=1;i<=n;i++)
		   {
			   int a=in.nextInt();
			   if(i%6==0 || i%6==2 || i%6==5)
				   sum^=a;
		   }
		   System.out.print("Case "+k+++": ");
		   if(sum!=0)
			   System.out.println("Alice");
		   else
			   System.out.println("Bob");
		}
	}
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值