1. 程式人生 > >Codeforces Round #114 (Div. 1) C Wizards and Numbers

Codeforces Round #114 (Div. 1) C Wizards and Numbers

swa ble style out 數字 pac 如果 div for

題目鏈接: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; }

Codeforces Round #114 (Div. 1) C Wizards and Numbers