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

题意:有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;
}

 

posted @ 2018-09-20 23:06  KirinSB  阅读(204)  评论(0编辑  收藏  举报