Codeforces Round #114 (Div. 1) C Wizards and Numbers
题目链接:Wizards and Numbers
题意:有两个数字a, b,假设 a>b,两个玩家进行游戏,有两种操作:1. 令 a=a-b^k,k为正数,且需要保证操作后 a 仍然非负;2. 令 a=a%b。最终有一个人无法操作(存在一个数为0)的时候便输了。
题解:如果只有操作2就是一个辗转相除法,实际上加上了操作1,执行的过程中也一定会出现辗转相除法种每轮的数字情况。所以以辗转相除法的每轮情况作为分段点,讨论其是必胜态还是必败态,首先(t, 0) 一定是必败态,所以其上一层的状态一定是必胜态。主要考虑当前层为必胜态,那上一层的情况为什么,问题实际上可以转化为有 tx 堆石子,每次可以 x的幕次颗,谁最先取光谁就输了。打个表找找规律便可以了:若 x 为奇数,则结果与 t 的奇偶有关;若 x 为偶数,则会在 x^2 处作为分界点,规律发生了变化,但还是很显然的。
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL xx[105],yy[105],cnt; LL gcd(LL x,LL y){ int res=(y==0?x:gcd(y,x%y)); xx[++cnt]=x; yy[cnt]=y; return res; } LL ans[105]; bool check(LL a,LL b){ if(a%2==1){ return (b/a-1)%2; } else{ if(a>=1000000000||b<a*a){ return !((b/a)%2); } else{ LL res=b/a; LL c1=(res%(a+1))%2; LL c2=res%(a+1); return !c1||(c2==a); } } } void solve(LL a,LL b){ cnt=0; gcd(a,b); ans[1]=0; for(int i=2;i<=cnt;i++){ if(ans[i-1]==0) ans[i]=1; else if(check(yy[i],xx[i]-yy[i-1])) ans[i]=1; else ans[i]=0; } if(ans[cnt]) printf("First\n"); else printf("Second\n"); } int p=12; int biao[100005]; int dabiao(int x){ if(biao[x]!=-1) return biao[x]; if(x<0) return 0; int temp=p; int flag=0; while(temp<=x*p){ if(dabiao(x-temp/p)==0){ flag=1; break; } temp*=p; } return biao[x]=flag; } int main(){ /******* memset(biao,-1,sizeof(biao)); biao[0]=1; dabiao(100); for(int i=1;i<=100;i++){ cout<<i<<" "<<biao[i]<<endl; } *******/ int n; cin>>n; while(n--){ LL a,b; cin>>a>>b; if(a<b) swap(a,b); if(b==0) cout<<"Second"<<endl; else if(a%b==0) cout<<"First"<<endl; else solve(a,b); } return 0; }