1067:取石子游戏:威佐夫博奕详细推导

题目大意

题目链接
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。

思路分析

各种博弈基础
一个半月,以一道博弈题poj 破百!继续努力

首先我们规定: 后手必胜态被称为奇异局势,(0,0)
想一下(0,0)的下一个奇异局势是什么?

(2,1)
如果先手取走“1”中的1个,那么后手就从“2”中取出2个,此时取完,所以后手胜利。

如果先手取走“2”中的2个,那么后手取走“1”中的1个,此时取完,后手胜利。

如果先手取走“2”中的1个,那么后手就在两堆中各取走1个,此时取完,后手胜利。

如果先手在“1”和“2”各取走了1个,那么后手取走“2”中的1个,此时取完,后手胜利。

再下来是什么?

0: (0,0)
1: (1,2)
2: (3,5)
3: (4,7)
4: (6,10)
5: (8,13)

我们发现,第i个奇异局势的差值是i
我们发现,每一个状态的第一个都是以前没有出现过的最小非法整数。

证明:

假设第k个局势为(x, k + x)
如果先手缩小差值,后手可以变成先前的局势,然后死了,所以先手不会着么做。

如果x是之前已经出现过的数, 那么先手肯定可以缩小,取到与x匹配的奇异局势,后手死了。

如果x比mex大,可以两堆缩小成x = mex,然后后手又死了。

所以当且仅当x = mex时(x, k + x)为奇异局势。

显然地,全体正整数被奇异局势分割成两个不相交的集合。

乱搞之中,我们想到了beatty定理。
在这里插入图片描述
我们发现,相邻奇异局势的第一个数的差值是1或2,但分布过于玄学,所以我们可以认为第一个数被表示成 a n \lfloor an \rfloor ,n为任意正整数,a为一无理数。
在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
using namespace std;

int n, m;

const double lorry = (sqrt(5.0) + 1.0) / 2.0;

int main() {
	while (cin >> n >> m) {
		if (n < m) swap(n, m);
		int a = n - m;
		if (m == int(lorry * (double)a))
			cout << 0 << endl;
		else
			cout << 1 << endl;
	}
}
发布了186 篇原创文章 · 获赞 13 · 访问量 9287

猜你喜欢

转载自blog.csdn.net/csyifanZhang/article/details/105262768
今日推荐