zoukankan      html  css  js  c++  java
  • 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
    ");
        else printf("Second
    ");
    }
    
    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;
    }
  • 相关阅读:
    进程和线程
    VC中使对话框全屏的方法
    初为项目经理
    Sqlite知识小记
    ERROR L105: PUBLIC REFERS TO IGNORED SEGMENT
    RTX51.LIB NOT FOUND
    Virtual Villagers 攻略
    专业术语常用名词缩写中英文对照
    Eric的四个无刷新(异步更新)示例
    ASP.NET 安全认证(一)—— 如何运用 Form 表单认证 .
  • 原文地址:https://www.cnblogs.com/N-Psong/p/10281699.html
Copyright © 2011-2022 走看看