POJ2315(nimK博弈)

题目链接

题意:有n<=30个足球,分别距离球门a[i]厘米。A、B两位同学每次可以选择其中一些球,最多为m(半径为R),然后踢他们。每次可以踢整数圈且不能超过L<=1e9。踢进最后一个足球的获胜,问谁获胜。

首先对于每个足球每一圈转 ( 2 ∗ P I ∗ R ) (2* PI * R) 2PIR厘米,这样我们可以得知每次要转多少圈到球门,设为 t t t,以及每次允许转的圈数,设为 k k k。(这不就是bash博弈吗,每次可以控制的圈数为 ( k + 1 ) (k+1) (k+1那么每个球的SG函数就为 t % ( k + 1 ) t \% (k+1) t%(k+1)
但是每次允许我们选 1 1 1 ~ m m m个球出来,类比Nim博弈,实际上Nim博弈,Nim博弈实际上是让我们选择 1 1 1~ 1 1 1个球,其答案是对各个数的二进制下做异或而判断的,而异或则是模 2 2 2加法,那么一次选m个实际上是模 ( m + 1 ) (m+1) m+1)的加法,所以可以二进制下做模 ( m + 1 ) (m+1) m+1)加法得到是否为0来判断答案。

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
int n,m,l,r;
const double pi = acos(-1.0);
int a[50];
int main(){
	while(~scanf("%d%d%d%d",&n,&m,&l,&r)){
		int k = l/(2*pi*r);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]),a[i]=a[i]/(2*pi*r)+1,a[i]=a[i]%(k+1);
		}
		int flag=0;
		while(1){
			int tmp = 0;
			int end = 1;
			for(int i=1;i<=n;i++){
				tmp += a[i]%2;
				tmp %= (m+1); 
				a[i]/=2;
				if(a[i])end=0;
			}
			if(tmp){
				flag=1;
				break;
			}
			if(end)break;
		}
		puts(flag?"Alice":"Bob");
	}
	return 0;
} 
//2进制下对2取余是nim博弈,对其他取余是num-k博弈 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值