题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1525
34 12 15 24 0 0
Stan wins Ollie wins
题目意思:
两个人,两堆石头,玩游戏。每次从石头数多的那堆中拿走石头数少的那堆石头的个数的倍数个,保证拿了过后不能为负数。谁恰好使其中一堆石头数为0,谁使其中某一堆石头为0,谁赢。两人都足够聪明。
解题思路:
借助欧几里得算法的博弈。
显然如果a>b 且a>2*b 先拿者必赢 因为他可以决定是自己还是对手遇到状态(a%b,b)如果状态(a%b,b)为必输状态,他就让对手面对(拿走a-a%b个)。如果为必赢状态,他就自己面对(拿走-a%b-b个).
如果b<a<=2*b 只能到达(a%b,b)的状态。
代码:
//#include<CSpreadSheet.h>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
int gcd(ll a,ll b)
{
    if(a<b) //求出谁大
        swap(a,b);
    if(b==0) //终止 必输状态
        return 0;
    if(a>2*b) //必胜
        return 1;
    return gcd(b,a%b)^1; //和拿了之后的输赢情况相反
}
int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   ll a,b;
   while(scanf("%I64d%I64d",&a,&b))
   {
       if(!a&&!b)
          break;
       int ans=gcd(a,b);
       if(ans)
            printf("Stan wins\n");
       else
            printf("Ollie wins\n");
   }
   return 0;
}
[简单博弈] hdu 1525 Euclid's Game,布布扣,bubuko.com
原文:http://blog.csdn.net/cc_again/article/details/27533479