[博弈论][数论][YandexAlgorithm2013T3]Board Game

来源:互联网 发布:mac定制无瑕粉底液色号 编辑:程序博客网 时间:2024/04/30 06:32

Board Game

Time limit1 secondMemory limit256MbInputstdinOutputstdout

Legend

Yura and Roma love playing board games. One of the recent favorites is board game “Atoms” by HAL. Its rules are as follows. Gaming set consists of a small number of atoms (approximately10100). In the beginning of the game, a polyhedron with all numbers from 1 to2 ⋅ 109 written on its sides is rolled. LetN be the result of rolling the polyhedron. The start position of the game can then be described asN groups of atoms, numbered from 1 to N, where group number i consists of i atoms.

Two players make moves in turn. A turn consists in taking any positive integer number of atoms from any one non-empty group of atoms and removing them from the game. The player who can not make a move loses the game.

Yura loves to collect fun facts about the “Atoms” boardgame. Today he wondered how many different first moves are possible. Roma managed to answer the question quickly, so Yura came up with another one: how many different first moves lead to the winning of the first player if both players play optimally? Roma couldn't answer the question right away so they decided to calculate the answer manually.

Input format

The only line of input holds one positive integer N (1 ≤ N ≤ 2 ⋅ 109): the result of rolling the polyhedron.

Output format

Print two integers: answers to the first and the second question, in that order.

Sample 1

InputOutput
1
1 1

Sample 2

InputOutput
2
3 1

Sample 3

InputOutput
3
6 0


做了整整24小时。思路比较复杂,代码却简短得让人生气。果然还是太菜了。


基本的nim游戏上增加了一个限制,每一堆的石子数依次为1、2、3……n。

求解的数量,所以求初始状态的sg函数无法实现,sg函数只能够判断是否存在解。


最直接的想法是枚举S-->Ti。想到用搜索。与题目给的数据范围差距太大。

之前的一个限制派上了用场,1、2、3……n。观察发现:从任意一堆中取若干石子,只存在两种情况:

1、该堆的石子全部取完。

2、该堆取走部分后和另外一堆相同。而A xor A = 0,而任何数异或0都不变,因此这两堆可以去除。


现在要求该局面Ti的sg函数,转化一下就是:

1、Sg(T1) = 2 xor 3 xor 4 xor …… n

    Sg(T2) = 1 xor 3 xor 4 xor …… n

    ……

    而有性质 A xor B xor B = A。

所以 Sg(Ti) = Sg(S) xor i。

(Sg(S)即1 xor 2 xor 3 …… xor n)

我们只需统计Sg(Ti)=0的个数,

即Sg(S) xor i = 0,即 i = Sg(S)


2、同上道理,并且有A xor B xor C = A xor (B xor C)

i xor j = Sg(S)


现在问题就在求Sg(S),即1 xor 2 xor 3 xor …… n。

当然,观察容易得到结果。

Sg(S) =

n (if n % 4 == 0)

1 (if n % 4 == 1)

n+1 (if n % 4 == 2)

0 (if n % 4 == 3)

用归纳法很容易证明。

别的证明方法可见点击打开链接


现在可以开始求解了:

分类讨论。


当 n%4 = 1,Sg(S) = 1

a = 1 且 1 ≤ a ≤ n 这样的a存在1个。

a xor b = 1 且 1 ≤ a ≤ b ≤ n 这样的(a,b)存在[n / 2]个(除了最后一位不同,其余都相同)

答案是[n / 2] + 1


当n%4 = 3,Sg(S) = 0

a = 0 且 1 ≤ a ≤ n 这样的a不存在。

a xor b = 0,a≠b,所以不存在。

答案是0


当n%4 = 0,Sg(S) = n

a = n 且 1 ≤ a ≤ n 这样的a存在1个

a xor b = n 且 1 ≤ a ≤ b ≤ n 这样的(a,b)的组数可以这样计算:

保留n的最高位,去除其他位,得到m。n-m即为所求。

证明:假设n有k+1位,m=2^k。

1、要使a xor b = n,则a 和 b 中有且仅有一个数和 n 位数相同。不妨设为a,因此a >= 2^k,又 a <= n 。必要性得证。

2、对于∀a ∈ [2^k,n-1],∃b ∈ [1,2^k-1],使a xor b = n。充分性得证。

因此答案如上。


当n%4 = 2,Sg(S) = n+1

a = n 且 1 ≤ a ≤ n 这样的a存在1个

a xor b = n 且 1 ≤ a ≤ b ≤ n 这样的(a,b)的组数看起来比上一种情况要多一种,是n-m+1。但是小心,多出来1 xor n = n+1这种与前面这种情况重复了。所以其实n%4=0和n%4=2代码完全相同。


思路实在是很繁琐。也许是方法不优的原因。坐等官方题解。

#include <cstdio>int main(){int n;scanf("%d",&n);long long tt = n;printf("%lld ",tt*(tt+1)/2);int ans = 0;int cnt = -1;int tmp;switch (n % 4){case 1://sg0 = 1;ans = n>>1;ans ++;printf("%d",ans);break;case 0://sg0 = n;case 2://sg0 = n+1;tmp = n;while (tmp){cnt ++;tmp >>= 1;}ans = n-(1<<cnt);ans ++;printf("%d",ans);break;default://sg0 = 0;printf("0");break;}return 0;}

原创粉丝点击