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; }