1. 程式人生 > >洛谷 P1290 歐幾里德的遊戲 題解

洛谷 P1290 歐幾里德的遊戲 題解

一、題目:

洛谷原題

二、思路:

什麼數論,什麼歐幾里得演算法,都不需要!要的只是搜尋和記憶化!

看到題,沒思路。考慮了SG函式,太暴力。這麼大的資料範圍似乎過不去。索性打打試試!

woc!60分!這題資料好水水啊!

再一看,加個記憶化好像沒毛病。交上去,A了!!!

這就是記憶化的重要性。

SG函式基本原理詳見《演算法競賽進階指南》\(P_{180}\)

三、程式碼:

/*
 * @Author: 岸芷汀蘭
 * @Date: 2018-10-31 22:18:01
 * @LastEditors: 岸芷汀蘭
 * @LastEditTime: 2018-10-31 23:04:41
 * @Description: P1290 of luogu
 */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>

typedef long long LL;
#define mem(s,v) memset(s,v,sizeof(s))

using namespace std;
template<class Type>
inline Type read(void){
    Type x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return f*x;
}

int m,n;

map<pair<int,int>,int>f;//用二維陣列要爆空間,所以用map。

bool solve(int a,int b){
    if(a>b)a^=b^=a^=b;
    if(f.find(make_pair(a,b))!=f.end())return f[make_pair(a,b)];
    if(b%a==0)return f[make_pair(a,b)]=true;
    for(register int k=1;a*k<=b;++k){
        if(!solve(a,b-k*a))return f[make_pair(a,b)]=true;
    }
    return f[make_pair(a,b)]=false;
}

int main(){
    int T=read<int>();
    while(T--){
        m=read<int>();n=read<int>();
        if(solve(m,n))puts("Stan wins");
        else puts("Ollie wins");
    }
    return 0;
}