Luogu 欧几里德的游戏

Luogu P1290 欧几里德的游戏

  • 又是如一的博弈论题,我们用形象的文字代替复杂的 (SG) 函数来说明.
  • 首先,题目给定有两个数字,这里设为 ((x,y))(x>y) ,我们可以发现,每次操作可以总体分为两种情况:
    • ([1]) 在操作时,只有唯一一种操作 (x-y) ,也就是说 (x<y*2) ,操作时固定的,只能减一次 (y)
    • ([2]) 在操作时,没有唯一一种操作方式, (x) 可以减去 (y) 的2倍及以上,如既可以 (x-y),也可以 (x-2*y),或是 (x-3*y),也就是说 (x>y*2),这样子操作就不是固定的,可以减多次 (y)
  • 我们假设1号选手拿到了有多次操作方式的那一步,那1号选手就可以根据后面出现的第一种情况的次数的奇偶性调整策略,从而再次拿到有多次操作方式的那一步,再接着控制形式。所以说,我们只需要判断先手和后手哪个人可以优先拿到有多种操作方式的情况即可
  • 注意,有一种情况是 (x=y) (特判),这时,先手一定获胜。
  • 接下来就是一点也不激动人心的代码了:
#include<bits/stdc++.h>//Forever_chen
#define RT register
using namespace std;
template<class t> inline t read(t &x){
	char c=getchar();bool f=0;x=0;
	while(!isdigit(c)) f|=c=='-',c=getchar();
	while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
	if(f)x=-x;return x;
}
template<class t>inline void write(t x){
	if(x<0)putchar('-'),write(-x);
	else{if(x>9)write(x/10);putchar('0'+x%10);}
}
template<class t>inline void writeln(t x){
	write(x);putchar('
');
	return;
}
template<class t>inline void write_blank(t x){
	write(x);putchar(' ');
	return;
}
int c,n,m,pd;
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	read(c);;
	while(c--){
		read(m);
		read(n);
		pd=0;
		if(m<n){
			swap(m,n);
		} 
		if(n==m){
			cout<<"Stan wins"<<endl;
			continue;
		}
		while(m<n*2){
			m-=n;
			pd++; 
			if(m<n){
				swap(m,n);
			} 
			if(m>n*2){
				break;
			}
		}
		if(pd&1)cout<<"Ollie wins"<<endl;
		else cout<<"Stan wins"<<endl;
		
	}
	//system("pause");
	return 0;
}
原文地址:https://www.cnblogs.com/Forever-chen/p/12838781.html