1. 程式人生 > >HDU2177 取(2堆)石子遊戲(威佐夫博弈)

HDU2177 取(2堆)石子遊戲(威佐夫博弈)

代碼 mat swap 輸出 tor pro pri 取石子 desc

HDU2177 取(2堆)石子遊戲

Problem Description

有兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在兩堆中同時取走相同數量的石子。最後把石子全部取完者為勝者。現在給出初始的兩堆石子的數目,如果輪到你先取,假設雙方都采取最好的策略,問最後你是勝者還是敗者。如果你勝,你第1次怎樣取子?

Input

輸入包含若幹行,表示若幹種石子的初始情況,其中每一行包含兩個非負整數a和b,表示兩堆石子的數目,a和b都不大於1,000,000,且a<=b。a=b=0退出。

Output

輸出也有若幹行,如果最後你是敗者,則為0,反之,輸出1,並輸出使你勝的你第1次取石子後剩下的兩堆石子的數量x,y,x<=y。如果在任意的一堆中取走石子能勝同時在兩堆中同時取走相同數量的石子也能勝,先輸出取走相同數量的石子的情況.

Sample Input

1 2 
5 8
4 7
2 2
0 0

Sample Output

0
1
4 7
3 5
0
1
0 0
1 2

# 題解

題意

中文題面

思路

威佐夫博弈的標準模型,至於取法的情況,可以先行枚舉都去i個,i<=a的情況進行判斷;然後枚舉,從較大堆取的情況,防止重復。

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
int T;


int main() {
    int a,b,m,n;
    double eqa = (sqrt(5)+1)/2;
    while(~scanf("%d %d",&a,&b)){
        if(a==0&&b==0)  break;
        if(a>b) swap(a,b);
        int k = b-a;
        if(a==(int)(k*eqa)) printf("0\n");
        else{
            printf("1\n");
            for(int i=1;i<=a;i++){
                m = a-i,n =b-i;
                k = n-m; 
                if((int)(k*eqa) == m)   printf("%d %d\n",m,n);
            }
            for(int i=1;i<=b;i++){
                m = a,n = b-i;
                if(m>n) swap(m,n);
                k = n-m;
                if((int)(k*eqa)==m) printf("%d %d\n",m,n);
            }
        }
    }
    return 0;    
}

HDU2177 取(2堆)石子遊戲(威佐夫博弈)