一、尼姆游戏
给定 N 堆物品,第 i 堆物品有 Ai 个。两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品者获胜。两人都采取最优策略,问先手是否必胜。
结论:每一堆异或起来,等于0,先手必败,否则先手必胜。
#include <cstdio>
using namespace std;
int n, x, ans;
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++ i) {
scanf("%d", &x);
ans ^= x;
}
if(ans == 0) puts("No");
else puts("Yes");
return 0;
}
二、巴什博弈
有 1 堆石子,总个数是 n ,两名玩家轮流在石子堆中拿石子,每次至少取 1 个,至多取 m 个。取走最后一个石子的玩家为胜者。判定先手和后手谁胜。
结论:若n%(m+1) ! =0 先手必胜,否则先手必败。
int main() {
scanf("%d%d", &n, &m);
if (n % (m + 1))
puts("first win");
else
puts("second win");
return 0;
}
三、威佐夫博弈
有两堆石子,石子数可以不同。两人轮流取石子,每次可以在一堆中取,或者从两堆中取走相同个数的石子,数量不限,取走最后一个石头的人获胜。判定先手是否必胜。
结论:若(b-a)*(+1)/2==a,则先手必败,否则先手必胜。
scanf(" %lld %lld",&a,&b);
if(a>b)
{
long long t=a;a=b;b=t;
}
long long c=b-a;
int d=((sqrt(5.0)+1.0)/2.0*c);
if(a==d)printf("0\n");
else printf("1\n");
四、斐波那契博弈
有一堆个数为 n ( n ≥ 2 ) 的石子,游戏双方轮流取石子,规则如下:
1、 先手不能在第一次把所有的石子取完,至少取 1 颗;
2、之后每次可以取的石子数至少为 1 ,至多为对手刚取的石子数的 2 倍。
约定取走最后一个石子的人为赢家,求必败态。
结论:当n为Fibonacci数的时候,先手必败,否则先手必胜。
fib[1] = 1;
fib[2] = 1;
for(int i = 3;i <= 50; ++ i) f[i] = f[i-1] + f[i-2], mp[f[i]] = 1;
while(scanf("%d", &x) && x != 0)
puts(mp[x] == 1 ? "Second win" : "First win");