HDU 1525

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1525

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

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
 
作为一道博弈题,我这种只会套模板不会动脑筋的咸鱼只好完全听从网上题解的话,老老实实找规律……
 
题意:
有2个数,2个人轮流把大的数(设为a)减去小的数(设为b)的倍数(不能超过大的数),一直到有一方能把某个数减到0,该方获胜。Stans先走,问最后赢的是谁。
 
题解:
首先我们把这对数按(a,b)(始终假设使得a>b,这个对于实际操作时没有影响,只是方便操作)表示;
  情况①:(a,b)满足b == 0,这个时候是必败局。
  情况②:(a,b)满足a%b == 0,这个时候,便是必胜局。
  情况③:(a,b)满足a/b >= 2(但a%b != 0),那么当前操作者肯定可以把(a,b)变成(a%b,b)或者(a%b+b,b),而因为对于任意一个(a,b)要么是必胜局,要么是必败局;
      故在参赛者是最聪明最有预见性的前提下,那么他必然可以得知(a%b,b)是必胜局还是必败局;
      若(a%b,b)是必胜局,直接做(a,b)→(a%b+b,b)操作,那么对手必然只能做(a%b+b,b)→(a%b,b)操作,这样就可以使得我们得到必胜局情形。
      若(a%b,b)是必败局,那么直接做(a,b)→(a%b,b)操作,使得对手面对必败局情形,这样我们依然是必胜。
      故综合以上情况,情况③是必胜局情形。
  情况④:(a,b)满足b<a<2*b,这种情况,我们只有一种选择,就是做(a,b)→(a-b,b)操作,这时只能老老实实继续操作下去,直到遇到必败局或者必胜局为止。
 
这样,我们便把游戏所有的情况都列举了出来,具体考虑怎么写成代码,也可以参考上面的情况写:
①首先保证a>b(通过if+swap);
②设定一个布尔类型的winner变量,winner==1代表Stan(先手)赢,winner==0代表Ollie(后手)赢;
③做一个while(1)的循环
  ④判断b==0?,若为真,当前操作者面对必败局,故winner=!winner,然后break;
  ⑤判断a%b==0 或者a/b >= 2 ?,若为真,则当前操作者面对了必胜局,直接break;
  ⑥剩下的情况只可能是上前列举的“情况④”,这时老老实实a-=b,swap(a,b),winner!=winner,代表当前操作者别无选择,只能按规则操作,并且下一步操作者变成对方。
⑦输出谁是胜者。
 
AC代码:
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int a,b;
 5 bool winner;
 6 int main()
 7 {
 8     while(scanf("%d%d",&a,&b) && a!=0 && b!=0)
 9     {
10         if(a<b) swap(a,b);
11         winner=1;
12         while(1)
13         {
14             if(b==0)
15             {
16                 winner=!winner;
17                 break;
18             }
19             if(a%b==0 || a/b>=2) break;
20             a-=b;
21             swap(a,b);
22             winner=!winner;
23         }
24         printf("%s wins
",winner?"Stan":"Ollie");
25     }
26 }
原文地址:https://www.cnblogs.com/dilthey/p/7512023.html