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和,就能判断胜负了。
代码:
#include
#include
#include
using namespace std;
int main()
{
int t,k=0,x,n;
scanf("%d",&t);
while(++k<=t)
{
int ans=0;
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&x);
if(i%6==0||i%6==2||i%6==5)
ans^=x;
}
if(ans)
printf("Case %d: Alice\n",k);
else
printf("Case %d: Bob\n",k);
}
return 0;
}
参考博客:ACdreamer Firstdeep kuangbin