题目链接:点这里。
Problem Description
Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be nonnegative. Then Ollie, the second player, does the same with the two resulting numbers, then Stan, etc., alternately, until one player is able to subtract a multiple of the lesser number from the greater to reach 0, and thereby wins. For example, the players may start with (25,7):
25 7
11 7
4 7
4 3
1 3
1 0
an Stan wins.
Input
The input consists of a number of lines. Each line contains two positive integers giving the starting two numbers of the game. Stan always starts.
Output
For each line of input, output one line saying either Stan wins or Ollie wins assuming that both of them play perfectly. The last line of input contains two zeroes and should not be processed.
Sample Input
34 12
15 24
0 0
Sample Output
Stan wins
Ollie wins
【题意】
一开始有两个数,两个人相互操作,每次选择大的数字减去小的数字的n倍,n可以自己指定,但是不能减成负数。最早将某个数字变成0 的人获胜,问你最后谁会胜利。
【分析】
没那么典型就只能一点点分析呗。
假设a>=b。显然如果不满足就swap一下就行。
首先,如果a是b的倍数,显然是先手获胜。
其次,如果b <= a < b*2那么当前状态只有一个后继,直接计算后继的状态就可以取反得到当前状态。
再次,如果b*2 <= a,那么当前状态一定是必胜的,为什么呢,其实也不难想,因为他的后继至少有两个(b,a-b),(b,a-b*2),而且前者可以转化成后者,所以后继中这两个一定是一胜一败,所以当前状态一定是必胜的。
然后直接对应上面的推导写程序就行了。
【代码】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<sstream>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define sin1(a) scanf("%d",&(a))
#define sin2(a,b) scanf("%d%d",&(a),&(b))
#define sll(a) scanf("%lld",&(a))
#define sll2(a,b) scanf("%lld%lld",&(a),&(b))
#define sdo(a) scanf("%lf",&(a))
#define sdo2(a,b) scanf("%lf%lf",&(a),&(b))
#define inf 0x3f3f3f3f
#define lson i<<1,l,mid
#define rson ((i<<1)|1),mid+1,r
#define uint unsigned int
typedef pair<int,int> PII;
#define A first
#define B second
#define pb push_back
#define MK make_pair
#define ll long long
template<typename T>
void read1(T &m)
{
T 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();
}
m = x*f;
}
template<typename T>
void read2(T &a,T &b)
{
read1(a);
read1(b);
}
template<typename T>
void read3(T &a,T &b,T &c)
{
read1(a);
read1(b);
read1(c);
}
template<typename T>
void out(T a)
{
if(a>9) out(a/10);
putchar(a%10+'0');
}
template<typename T>
void outn(T a)
{
if(a>9) out(a/10);
putchar(a%10+'0');
puts("");
}
using namespace std;
///------------------------------------------------------------------------------------
int main()
{
// freopen("in.txt","r",stdin);
int a,b;
while(sin2(a,b),a||b)
{
if(a<b) swap(a,b);
bool flag=true;
while(1)
{
if(b==0||a%b==0||a/b>=2) break;
flag=!flag;
change(a,b);
}
puts(flag?"Stan wins":"Ollie wins");
}
return 0;
}