题意:有n<=30个足球,分别距离球门a[i]厘米。A、B两位同学每次可以选择其中一些球,最多为m(半径为R),然后踢他们。每次可以踢整数圈且不能超过L<=1e9。踢进最后一个足球的获胜,问谁获胜。
首先对于每个足球每一圈转
(
2
∗
P
I
∗
R
)
(2* PI * R)
(2∗PI∗R)厘米,这样我们可以得知每次要转多少圈到球门,设为
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博弈