有两堆物品,两人轮流取,可以从某一堆或同时两堆中取相同数量物品,规定每次至少取一个多者不限,去最后一个者获胜
我们先将(m,n),表示两堆物品的个数,成为局面。
1.我们发现当面对(n,n)(n不等于0),(0,n), (m,0)时,谁取谁胜
2,我们先说一个奇异局势(0,0),(1,2),(3,5)(4,7)(6,10)(8,13)(9,15)(11,17)
···········(ak,bk),ak为前面所有奇异局势未出现的最小正整数,k表示第几个,
奇异局势,bk=ak+k。
先看一下奇异局势的性质,
(1),任何自然数都包含在一个且仅有奇异局势中。
(这个从定义中可以看得出来)
(2),任何操作都可以将奇异局势转变为非奇异局势
证明:1.取任何一堆,一堆数量减少,有定义可知,局势将转变为非奇异
局势。
2.同时从两堆中取相同数量的物品,由于局势(ak,bk)转变为(a,b)
a-b=k;我们知道奇异局势两数之差为它的排行(它是第几个奇异
局势),我们又知啊a!=ak,b!=bk;所以(a,b)一定不是奇异局势
(3)采取适当的方法,可以将非奇异局势转变为奇异局势
#include<stdio.h>
#include<string.h>
#define MAXN 2500000
int num[MAXN];
bool B[MAXN];
int k;
void yuchuli(){
int i;
k=0;
memset(B,true,sizeof(B));
for(i=0;i<MAXN;i++)
if(B[i]){
num[k]=i;
if(i+k<MAXN)B[i+k]=false;
k++;
}
}
int Midfind(int low,int high,int x){
while(low<=high){
int mid=(low+high)/2;
if(num[mid]==x)return mid;
else if(num[mid]>x)high=mid-1;
else low=mid+1;
}
return -1;
}
int main(){
// freopen("Output.txt","w",stdout);
//freopen("Input.txt","r",stdin);
yuchuli();
int t,flag,tem;
/*for(i=0;i<100;i++)
printf("奇异局势=%d\t%d\n",num[i],num[i]+i);*/
scanf("%d",&t);
while(t--){
int s,e;
scanf("%d%d",&s,&e);
if(s>e){
tem=e;
e=s;
s=tem;
}
flag=Midfind(0,k-1,s);
// printf("flag=%d\n",flag);
if(flag==-1)
printf("A\n");
else if(s+flag!=e)
printf("A\n");
else
printf("B\n");
}
}
其实它是有通项公式的(ak,bk)ak=K*(1+sqrt(5))/2,bk=ak+k;
这题我没用通项公式,还有一题必须要用通项公式,还涉及到精确度的问题,恶心死我了今天,我没写对,最后直接提交了别人的代码,明天再写写吧