POJ-2315 Football Game (NIMK)

Football Game

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 389   Accepted: 147

Description

Alice and Bob both love football very much, and both of them are vanguards. They are both good at football control. One day after a football match, they play an interesting game, in which they shoot footballs forward the goal directly. There are N footballs in front of the goal, and they play this game in turn. For example, if it is Alice's turn, Alice can choice some footballs (the number of footballs mush equal or less than M) and shoot them forward. Because the footballs' quality is not very good, footballs are not a complete sphere and can only roll integer times of its girth. And because of restriction of the friction and strength of them, they cannot shoot a football farther then L centimeters. Of course, they know the radius of a football is R centimeters. Alice and Bob love this game very much. If both of them have unlimited IQ and precision shooting skill, can you guess who can win the football game? By the way, though Alice is as strong as Bob, Alice is a girl, so she will shoot first.

Input

The input consists of several cases, each of which contains two lines. 

For each test case, the first line contains 4 integers N, M, L and R (1 <= M <= N <= 30, 0 < L < 100000000, 0 < R < 10000), separated by a single space. N is the number of the footballs, M is the maximum number of footballs one player can shot in one turn, L is the maximum distance that a player can shoot, and R is the radius of footballs. 

The next line contains N numbers, S(1), S(2), ..., S(N) (0 < S(i) < 100000000), which describe the distance between footballs and the goal.

Output

For each case output contains one line describing the name of the winner.

Sample Input

2 1 30 1
8 14
2 1 30 1
8 12
2 1 30 1
8 10
2 1 30 1
40 200

Sample Output

Alice
Bob
Bob
Bob

Source

POJ Monthly,uni

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN = 50;
const double PI = acos(-1.0); //巧妙
int cnt[MAXN];     //cnt数组存的是球到球门的距离
int XOR[MAXN];     //储存每一个二进制位上的和在,这个是总和,即XOR存的就是最终所有数的和
/*我们采取的是对每堆的cnt值进行异或,异或其实就是对每一个cnt值二进制位上的数求和然后模2,
比如说3^5就是011+101=112,然后对每一位都模2就变成了110,所以3^5=6。
而NIMK游戏和NIM游戏的区别就在于模的不是2,如果是取m堆,就模m+1,*/
int solve(int n,int m)
{
    int i;
	memset(XOR,0,sizeof XOR);
	int maxn=-1;
	for(i=1;i<=n;i++)
	{
    	int temp=cnt[i];
		int num=0;
		while(temp)
		{
			XOR[num]+=temp&1;
			num++;
			temp>>=1;      //还是二进制的相加
		}
		maxn=max(maxn, num);  //存最大二进制位数。
	}
	for(i=0;i<maxn;i++)
    if(XOR[i]%(m+1))
    return 1;          //返回true表示先手必胜
	return 0;         //返回false表示先手必败
}
int main()
{
     int n,m,l,r;
     int k;
     int i;
	 while(scanf("%d%d%d%d",&n,&m,&l,&r)!= EOF)
	{
		k=l/(2*PI*r);       //每次踢出距离不超过L,将L除以周长,向下取整,得到每次至多能拿的石头个数K。                  
                           //这里的k与grundy的k的区别:任意。只是最大
		for(i=1;i<=n;i++)  //而grundy的k是用数组存的,不是任意的。
		{
			scanf("%d",&cnt[i]);
			cnt[i]=ceil(cnt[i]/(2*PI*r));//每个球到球门的距离除以周长得到一个数字cnt,向上取整,代表要踢多少圈才能进球。相当于有cnt的石头
			cnt[i]%=k+1;           //将每个cnt % (k+1),可以简化每个石头堆上的石头数,因为你拿走x个,我可以拿走k+1-x个,抵消你的操作,使得游戏状态不变。
		}                         //所以又有个技巧,能维持状态不变就一直维护,知道不能维护的情况就是最简情况
		if(solve(n,m))            //m是一次可以踢的堆数。
        printf("Alice\n");
		else
        printf("Bob\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xigongdali/article/details/81171396