1. 程式人生 > >POJ 1740 A New Stone Game(博弈)題解

POJ 1740 A New Stone Game(博弈)題解

const 證明 one int ios scan space return i++

題意:有n個石子堆,每一個都可以輪流做如下操作:選一個石堆,移除至少1個石子,然後可以把這堆石子隨便拿幾次,隨便放到任意的其他石子數不為0的石子堆,也可以不拿。不能操作敗。

思路:我們先來證明,如果某個石子數有偶數堆,則先手必敗,因為無論先手怎麽做,後手都能模仿先手,最後把石子取光。顯然全是偶數堆是必敗態。如果有奇數堆怎麽辦?我們就把最大的奇數堆取光,然後把其他奇數堆變成偶數堆。但是一定能保證可以嗎?答案是可以。假設奇數堆的石子數為 x1,x2,x3...xn,那麽我們分別給每一堆加上x2-x1,x3-x2...xn-xn-1,我們把這些我們加上的石子數加起來,發現我們一共用了xn-x1個石子,顯然小於等於(xn) -1個石子。

參考:POJ 1740 A New Stone Game 題解《挑戰程序設計競賽》

代碼:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const
int maxn = 100 + 10; const int seed = 131; const ll MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; bool vis[maxn]; int main(){ int n; while(~scanf("%d", &n) && n){ memset(vis, false, sizeof(vis)); for(int i = 0; i < n; i++){ int u; scanf(
"%d", &u); vis[u] = !vis[u]; } int flag = 0; for(int i = 1; i <= 100; i++) if(vis[i]) flag = 1; if(flag) printf("1\n"); else printf("0\n"); } return 0; }

POJ 1740 A New Stone Game(博弈)題解