hdu 1525
@[toc]
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和m两个数,两个人轮流进行操作,每次可以剪去i*min(n,m),i自定(剪去n和m中最小数的倍数),有一个数减到0即为胜利,问先手后手谁先赢
题解:
非正式解答:
一看是博弈论我就开始搜索我脑中的知识(发现为空)
直觉告诉我肯定有规律和公式,我便自造数据多次实验,最终发现最先遇到一个数是另一个数的两倍以上时,即可以成功(也就是(n/m>1),此处n>m),特殊情况是n和m相同时也是谁遇到谁赢。综合下就是:谁遇到n/m!=1时,谁就赢。
为什么呢?我是这么理解的,当遇到n/m>1时,此人可以选择减一个m,也可以选减多个m,而这对后面的情况是有影响的,而总有一种情况是对自己有利的,只要按照这个方向走,一定能赢(多局试验后得出)
当然如果全程n/m==1,那么双方的操作都是固定的,没有选择空间,因为都只能减一次,所以轮流操作,奇数个操作流程先手赢,反之后手赢
正式解答:
正规解答来自
令n为较小的数,m为较大的数,可以发现:
当m%n=0时,先手必胜
当m>=2n时,如果(m%n,m)为必胜态,先手可以先将局势变为(m%n+n,n),则后手只能将局势变为(m%n,n);如果(m%n,n)为必败态,先手可以直接将局势变为(m%n,n)。因此,不论(m%n,n)为什么态,先手都必胜
当2n>m>n时,那就是一步一步走下去,直到出现m%n=0||m>=2n结束
代码:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int main() { int n,m; while(cin>>n>>m) { if(n==0&&m==0)break; if(m>n)swap(n,m); int ans=1;//记录步伐 int f=-1; while(n!=0&&m!=0) { if(m>n)swap(n,m); if(n/m!=1||m==0) { f=ans; break; } ans++; n-=m; } if(f&1)cout<<"Stan wins"<<endl; else cout<<"Ollie wins"<<endl; } return 0; }