写在记录里面的,干脆单独摘出来算了
NIM博弈
nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就输了。
定理 (Nim)博弈先手必胜,当且仅当(A1xorA2xor...xorAn≠0)
公平组合游戏
公平组合游戏的定义如下:
- 游戏有两个人参与,二者轮流做出决策,双方均知道游戏的完整信息;
- 任意一个游戏者在某一确定状态可以作出的决策集合只与当前的状态有关,而与游戏者无关;
- 游戏中的同一个状态不可能多次抵达,游戏以玩家无法行动为结束,且游戏一定会在有限步后以非平局结束。
大部分的棋类游戏都 不是 公平组合游戏,如国际象棋、中国象棋、围棋、五子棋等(因为双方都不能使用对方的棋子)。
为了证明该定理,只需要证明下面三个定理:
- 定理 1:没有后继状态的状态是必败状态。
- 定理 2:对于 (a_1 xor a_2xor...xora_n eq 0) 的局面,一定存在某种移动使得(a_1 xor a_2xor...xora_n = 0) 。
- 定理 3:对于(a_1 xor a_2xor...xora_n = 0) 的局面,一定不存在某种移动使得 (a_1 xor a_2xor...xora_n = 0) 。
有向图游戏与 SG 函数
对于状态(x) 和它的所有 (k) 个后继状态(y_1,y_2...y_k) ,定义 (SG) 函数:
(SG(x) = 0)则对应了一个必败状态
对于由(n)个有向图游戏组成的组合游戏,设它们的起点分别为 (s_1,s_2...s_n),则有定理: 当且仅当 时(SG(s_1)xorSG(s_2)..xorSG(s_n) eq 0),这个游戏是先手必胜的。
这一定理被称作 SG 定理。
巴什博奕
有两个游戏者: (A) 和 $B $,有 (n) 颗石子。
约定:两人轮流取走石子,每次可取 (1,2,...,m) 颗。 (A)先取,取走最后一颗石子的人获胜。
定理:当局面为(k(m+1))时是先手必败的状态,如果(n \% (m+1)=0)则先手必败=
取火柴游戏(NIM升级)
(nim)游戏,不过在先手必胜态下,请构造出一个方法使后手必败
在所有石子中取一次,使异或和(=0),要求取得堆最靠前
我们把(xorsum)拿来,异或(a_i)得到除了(a_i)以外的异或和(xorsum'),然后看看(a_i)是否可以变成(xorsum')即可
威佐夫博弈
有两堆各若干个物品,两个人轮流从任一堆取至少一个或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
一些性质:
- ((a[k],b[k]))((a[k] ≤ b[k] ,k=0,1,2,...,n))表示两堆物品的数量并称其为局势,如果甲面对((0,0)),那么甲已经输了,这种局势我们称为奇异局势。前几个奇异局势是:((0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20))(注:k表示奇异局势的序号, 第一个奇异局势k=0)
- 可以看出,(a[0]=b[0]=0),(a[k])是未在前面出现过的最小自然数,而 (b[k]= a[k] + k)。
- 任何自然数都包含在一个且仅有一个奇异局势中。
- 任意操作都可将奇异局势变为非奇异局势。
- 采用适当的方法,可以将非奇异局势变为奇异局势。
总之有结论:
(a_k , b_k)为一个奇异局势,当且仅当(a_k=⌊k×25+1⌋,b_k=a_k+k)
即:先手必败当且仅当
斐波拉契博弈(Fibonacci Nim)
有一堆个数为 n 的石子, A,B轮流取石子,满足:
- 先手不能在第一次把所有的石子取完;
- 之后每次可以取的石子数介于 1 到对手刚取的石子数的 2 倍之间(包含 1 和对手刚取的石子数的 2 倍)。
特点:一方每次可以取的石子数依赖于对手刚才取的石子数。
Zeckendorf定理(齐肯多夫定理):任何正整数可以表示为若干个不连续的Fibonacci数之和
结论:先手必败残余石子为斐波拉契数
Good Luck in CET-4 Everybody!(SG函数与规律)
给一个递推sg函数的模板,复杂度(O(n^2))
SG[0] = 0;
for(int i=1;i<=1000;i++)
{
memset(mex,0,sizeof mex);
for(int j=0;i-(1<<j)>=0;j++)
mex[SG[i-(1<<j)]] = 1;//sg函数的递推方式,等于所有后续节点的sg的mex值
for(int j=0;j<=i;j++)
{
if(mex[j]) continue;
SG[i] = j;
break;
}
}
打表发现sg值是 (0 1 2 0 1 2 0 1 2 0 1 2...)
所有3的倍数sg值=0,即先手必败
Fibonacci again and again
有三堆石子,只能取斐波那契数个,
考虑一堆石子,可以直接向上一个题一样推SG函数
然后合并多个有向图的游戏,把三堆的SG函数异或起来得到整个有向图游戏的SG
单个堆不是一个后继节点,不能用mex,所以要用异或的方法求SG
打表发现sg值是一个循环节为10的循环
HDU1849 Rabbit and Grass
转化一波题意就是裸的nim游戏
Being a Good Boy in Spring Festival
裸的取火柴游戏,计算方案数即可
然后就是改代码加多组数据,忘了xorsum清空,弱智了
GZOI2015 T1 石子游戏
非常好的sg打表+找规律
要算质数的id
0先手必败,sg = 0
1的sg = 1
偶数的sg = 2
第i个质数的sg = i+1
1 的 sg = 1
剩下的试除法,第一个质因子的id+1就是 sg
inline int getsg(int x)
{
if(x == 0) return 0;
if(x == 1) return 1;
if(x % 2 == 0) return 2;
if(!flag[x]) return pid[x] + 1;
for(int i=1;i<=cnt;i++)
if(x % prime[i] == 0) return pid[prime[i]] + 1;
return 0;
}
多个有向图游戏求异或和就可以了
CF1194D 1-2-K Game
取石子类,取完胜,局面为0的为先手必败 故(sg(0) =0)
打表发现sg函数有以下特点
(k = 3),循环节为(0 1 2 3) ,(从0开始
(k = 其他数),循环节为$ 0 1 2$ (从0开始
题面给出(k >= 3)
然后我就wa了
发现(k)为(3)的倍数有不同的规律
(k = 6)时,循环节是(6),前面都是(012),第(6)个是(3)
(k = 9)时,循环节是(9),前面都是(012),第(9)个是(3)
先模一个(k+1),如果为(k)就是(3),否则就是再模一个(3)
移棋子游戏
典型的有向图游戏
多个棋子就是多个有向图游戏的和
(dfs)求(sg)函数,出度为(0)的(sg = 0)
nim游戏+取石子数限制
cao居然被这个题搞到
由于石子数被(S) 集合限制了,只能特定的求sg函数
然后把各个石子堆的sg值异或起来
给出第一步方案这个稍微有点把我搞到
由于选石子是在石子这个实际意义上的,而异或和是求的sg值的,我们要分开算
枚举当前堆取的(S)集合中的那个石子数,然后像取火柴游戏一样,得到一个方案
for(int j=1;j<=k;j++)
{
if(a[i] - b[j] >= 0 && (xorsum ^ sg[a[i]] ^ sg[a[i] - b[j]]) == 0)
{
puts("YES");
io << i << ' ' << b[j];
return 0;
}
}