洛谷P4548 [CTSC2006]歌唱王国
先了解一下概率生成函数,对于一个随机变量 a a a,它的概率生成函数是 F ( x ) = ∑ i ≥ 0 ( Pr ( a = i ) ⋅ x i ) F(x)=\sum\limits_{i\geq0}(\text{Pr}(a=i)\cdot x^i) F(x)=i≥0∑(Pr(a=i)⋅xi)对它求导得 F ′ ( x ) = ∑ i ≥ 0 ( Pr ( a = i ) ⋅ i ⋅ x i − 1 ) F'(x)=\sum\limits_{i\geq0}(\text{Pr}(a=i)\cdot i\cdot x^{i-1}) F′(x)=i≥0∑(Pr(a=i)⋅i⋅xi−1)根据期望的定义可得 E ( a ) = F ′ ( 1 ) \mathbb{E}(a)=F'(1) E(a)=F′(1)。
那么对于这道题,设 f i f_i fi表示,长度为 i i i的串结束(找到匹配)的概率, g i g_i gi表示长度为 i i i的串未结束(还没找到匹配)的概率。 f 0 = 0 f_0=0 f0=0, g 0 = 1 g_0=1 g0=1。
对随机变量 a 1 : = a_1:= a1:=结束时的长度 和随机变量 a 2 : = a_2:= a2:=未结束时的长度 分别定义概率生成函数: F ( x ) = ∑ i ≥ 0 ( f i ⋅ x i ) F(x)=\sum\limits_{i\geq0}(f_i\cdot {x}^i) F(x)=i≥0∑(fi⋅xi) G ( x ) = ∑ i ≥ 0 ( g i ⋅ x i ) G(x)=\sum\limits_{i\geq0}(g_i\cdot {x}^i) G(x)=i≥0∑(gi⋅xi)可知题目要求的是 E ( a 1 ) = F ′ ( 1 ) \mathbb{E}(a_1)=F'(1) E(a1)=F′(1)。
为什么要定义 g g g,当然是因为只定义 f f f不好算,定义了 g g g过后,我们能写 g g g的转移式: g i = f i + 1 + g i + 1 g_i=f_{i+1}+g_{i+1} gi=fi+1+gi+1相当于往长度为 i i i的串后面加一个字符,看能否结束,根据加法原理将两个概率相加。
于是有 F ( x ) + G ( x ) = ∑ i ≥ 0 [ ( f i + g i ) ⋅ x i ] = ∑ i ≥ 1 ( g i − 1 ⋅ x i ) + 1 = ∑ i ≥ 0 ( g i ⋅ x i + 1 ) + 1 = G ( x ) ⋅ x + 1 \begin{aligned} F(x)+G(x)&=\sum\limits_{i\geq0}\left[(f_i+g_i)\cdot x^i\right]\\ &=\sum\limits_{i\geq1}(g_{i-1}\cdot x^i)+1\\ &=\sum\limits_{i\geq0}(g_{i}\cdot x^{i+1})+1\\ &=G(x)\cdot x+1 \end{aligned} F(x)+G(x)=i≥0∑[(fi+gi)⋅xi]=i≥1∑(gi−1⋅xi)+1=i≥0∑(gi⋅xi+1)+1=G(x)⋅x+1两边同时求导得 F ′ ( x ) + G ′ ( x ) = G ′ ( x ) ⋅ x + G ( x ) F'(x)+G'(x)=G'(x)\cdot x+G(x) F′(x)+G′(x)=G′(x)⋅x+G(x)于是 E ( x ) = F ′ ( 1 ) = G ( 1 ) \mathbb{E}(x)=F'(1)=G(1) E(x)=F′(1)=G(1)
接下来就要考虑 G ( 1 ) G(1) G(1)怎么算了。直觉告诉我们,两个变量得两个方程,所以还需要找到一个本质不同的 g g g与 f f f的关系,这个时候肯定得跟原串(牛人酋长的名字) A A A扯上关系。既然 g i g_i gi是没有结束的概率,那么我们强制让它结束掉,不就和 f f f扯上关系了么。设字符集大小为 n n n, A A A的长度为 L L L。考虑把 A A A强制接在 g i g_i gi对应的某个串后面: g i ⋅ ( 1 n ) L = ∑ A [ 1 , ⋯ , d ] = A [ L − d + 1 , ⋯ , L ] f i + d ⋅ ( 1 n ) L − d g_i\cdot\left(\dfrac{1}{n}\right)^L=\sum\limits_{A[1,\cdots,d]=A[L-d+1,\cdots,L]}f_{i+d}\cdot\left(\dfrac{1}{n}\right)^{L-d} gi⋅(n1)L=A[1,⋯,d]=A[L−d+1,⋯,L]∑fi+d⋅(n1)L−d
如图对应了一种 f i + d ⋅ ( 1 n ) L − d f_{i+d}\cdot\left(\dfrac{1}{n}\right)^{L-d} fi+d⋅(n1)L−d的情况,即阴影部分相等。对于 g i g_i gi,强制规定上方的橙色部分,对于 f i + d f_{i+d} fi+d,强制规定白色方框部分。由于下方的橙色部分可以移动,所以对所有border的情况求和。
令 r i = [ A [ 1 , ⋯ , d ] = A [ L − d + 1 , ⋯ , L ] ] r_i={\large[}A[1,\cdots,d]=A[L-d+1,\cdots,L]{\large]} ri=[A[1,⋯,d]=A[L−d+1,⋯,L]],根据上式就有 G ( x ) ⋅ ( 1 n ) L ⋅ x L = ∑ 1 ≤ i ≤ L ( r i ⋅ F ( x ) ⋅ x L − i ) G(x)\cdot\left(\dfrac{1}{n}\right)^L\cdot x^L=\sum\limits_{1\leq i\leq L}\left(r_i\cdot F(x)\cdot x^{L-i}\right) G(x)⋅(n1)L⋅xL=1≤i≤L∑(ri⋅F(x)⋅xL−i)这个式子我只能暴力证明它是对的:怎么来的就只能感性认知了
于是得到 G ( 1 ) ⋅ ( 1 n ) L = F ( 1 ) ⋅ ∑ 1 ≤ i ≤ L ( r i ⋅ n i − L ) G(1)\cdot\left(\dfrac{1}{n}\right)^L=F(1)\cdot \sum\limits_{1\leq i\leq L}(r_i\cdot n^{i-L}) G(1)⋅(n1)L=F(1)⋅1≤i≤L∑(ri⋅ni−L)注意 F ( 1 ) = ∑ i ≥ 0 f i = 1 F(1)=\sum\limits_{i\geq0}f_i=1 F(1)=i≥0∑fi=1,因为无论怎样必定有一个时刻会结束,所以 E ( a 1 ) = G ( 1 ) = ∑ 1 ≤ i ≤ L ( r i ⋅ n i ) \mathbb{E}(a_1)=G(1)=\sum\limits_{1\leq i\leq L}(r_i\cdot n^i) E(a1)=G(1)=1≤i≤L∑(ri⋅ni)哈希或者KMP处理border( r i r_i ri),结束。
#include
#include
#include
const int MAXN = 100000;
const int MOD = 10000;
int Pow(int x, int y) {
int ret = 1;
while (y) {
if (y & 1)
ret = ret * x % MOD;
y >>= 1;
x = x * x % MOD;
}
return ret;
}
int N, L;
int S[MAXN + 5], Fail[MAXN + 5];
int main() {
int T, N;
scanf("%d%d", &N, &T);
N %= MOD;
while (T--) {
scanf("%d", &L);
memset(Fail, 0, sizeof Fail);
for (int i = 1; i <= L; i++)
scanf("%d", &S[i]);
for (int i = 2; i <= L; i++) {
int k = Fail[i - 1];
while (k && S[k + 1] != S[i])
k = Fail[k];
if (S[k + 1] == S[i])
Fail[i] = k + 1;
}
int Ans = 0;
for (int i = L; i; i = Fail[i])
Ans = (Ans + Pow(N, i)) % MOD;
printf("%04d\n", Ans);
}
return 0;
}