棋盘对角线状态:
暴力的做法是
O
(
n
m
)
O(nm)
O(nm)的。
用bitset按照斜对角线一条一条的做是
O
(
n
m
/
w
)
O(nm/w)
O(nm/w)的。
结论:对于
i
,
j
≥
3
i,j\ge3
i,j≥3,有
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
−
1
]
f[i][j]=f[i-1][j-1]
f[i][j]=f[i−1][j−1]。即从第三行第三列开始每个点与对角线上的前一个点相同。通过反证法可简单证明。
于是求出第二行第二列之后就可以
O
(
1
)
O(1)
O(1)得出任意一点的状态。
应用:AGC 002 E(注意此题是吃最后一颗糖的输)
应用:
f
[
l
]
[
r
]
=
!
(
f
[
l
+
1
]
[
r
]
&
f
[
l
]
[
r
−
1
]
)
f[l][r]=!(f[l+1][r]\&f[l][r-1])
f[l][r]=!(f[l+1][r]&f[l][r−1])。把
l
,
r
l,r
l,r看做x轴y轴,对每个
l
l
l求出最大的
r
r
r使得
s
[
l
,
r
]
s[l,r]
s[l,r]是
t
t
t的子串,并在
(
l
,
r
)
(l,r)
(l,r)处标记为必败态,那么相当于从
(
1
,
r
)
(1,r)
(1,r)走到边界:
求最大的
r
r
r就对
t
t
t建SAM,然后让
s
s
s在上面跑,如果跑不动了当前长度就是最大的
r
r
r,当
l
l
l增加时就让指针沿fail回退,如果回退后的
l
e
n
len
len等于当前长度就可以继续往下匹配,否则就是上一回的
r
r
r。
平等博弈,SG
感觉SG函数应该起源于Nim游戏。
-
两个人取石子,每次可以取 [ 1 , k ] [1,k] [1,k]个,不能取的输,求先手胜负。
S G [ i ] = i % ( k + 1 ) SG[i]=i\%(k+1) SG[i]=i%(k+1) -
两个人取石子,每次可以取 [ l , r ] [l,r] [l,r]个,不能取的输,求先手胜负。
S G [ i ] = i % ( l + r ) l SG[i]=\frac {i\%(l+r)}l SG[i]=li%(l+r) -
一个1*n的木条,每次可以取连续的两个格子, S G [ n ] SG[n] SG[n]从 n = 1 n=1 n=1开始依次为:
只需要打完表后放入记事本中,打开自动换行,再慢慢拖动边框,就可以发现循环节了(奇怪的知识增加了!,注意这个循坏是在第三行后才一模一样的。
例1:SPOJ11414 COT3 【博弈论 + Trie树合并】
记
f
[
u
]
[
v
]
f[u][v]
f[u][v]表示
u
u
u的子树中翻转
u
→
v
u\to v
u→v这条路径后的SG值,那么
f
[
f
a
]
[
v
]
=
f
[
u
]
[
v
]
⊕
(
f
a
的
其
它
子
树
的
S
G
值
)
f[fa][v]=f[u][v]\oplus(fa的其它子树的SG值)
f[fa][v]=f[u][v]⊕(fa的其它子树的SG值)。需要维护一个数据结构,支持整体异或上
k
k
k,合并,求mex。Trie树比较合适。
题解&Code
例2:Codeforces 1091 H【bitset优化求SG】
题解
问题转化之后变为求
S
G
[
x
]
=
m
e
x
d
(
S
G
[
x
−
d
]
)
SG[x]=mex_{d}(SG[x-d])
SG[x]=mexd(SG[x−d])。直接做是
O
(
n
2
)
O(n^2)
O(n2)的。
暴力打表之后发现SG值普遍很小,<=100。
设
b
i
t
s
e
t
f
[
i
]
bitset~f[i]
bitset f[i]表示有哪些位置的后继中存在
S
G
=
i
SG=i
SG=i。
那么更新就是
f
[
S
G
[
x
]
]
∣
=
D
<
<
x
f[SG[x]]|=D<<x
f[SG[x]]∣=D<<x。求
S
G
[
x
]
SG[x]
SG[x]就枚举
i
i
i然后看
f
[
i
]
[
x
]
f[i][x]
f[i][x]是否为0即可。
复杂度
O
(
n
∗
S
G
+
n
2
w
)
O(n*SG+\frac {n^2}w)
O(n∗SG+wn2)
N阶Nim游戏
下面这一段是摘自clover_hxy:Nim 游戏及其变形
n堆石子,每次从不超过k堆中取任意多个石子,最后不能取的人失败。
这是一个nim游戏的变形,也是有结论的。
结论为:把n堆石子的石子数用二进制表示,统计每个二进制位上1的个数,若每一位上1的个数mod(k+1)全部为0,则必败,否则必胜。
证明如下:
1.全为0的局面一定是必败态。
2.任何一个P状态,经过一次操作以后必然会到达N状态:在某一次移动中,至少有一堆被改变,也就是说至少有一个二进制位被改变。由于最多只能改变k堆石子,所以对于任何一个二进制位,1的个数至多改变k。而由于原先的总数为k+1的整数倍,所以改变之后必然不可能是k+1的整数倍。故在P状态下一次操作的结果必然是N状态。
3.任何N状态,总有一种操作使其变化成P状态。从高位到低位考虑所有的二进制位。假设用了某种方法,改变了m堆,使i为之前的所有位都回归到k+1的整数倍。现在要证明总有一种方法让第i位也恢复到k+1的整数倍。
有一个比较显然的性质,对于那些已经改变的m堆,当前位可以自由选择1或0.
设除去已经更改的m堆,剩下堆i位上1的总和为sum
分类讨论:
(1)sum<=k-m,此时可以将这些堆上的1全部拿掉,然后让那m堆得i位全部置成0.
(2)sum>k-m 此时我们在之前改变的m堆中选择k+1-sum堆,将他们的第i位设置成1。剩下的设置成0.由于k+1-sum<k+1-(k-m)<m+1,也就是说k+1-sum<=m,故这是可以达到的。