luogu P4548 [CTSC2006]歌唱王国
https://www.luogu.com.cn/problem/P4548
%yml 2018年的论文%%%
PGF入门题
设
f
[
n
]
为
恰
好
在
第
n
次
结
束
的
概
率
,
g
[
n
]
为
在
第
n
次
之
后
结
束
的
概
率
设f[n]为恰好在第n次结束的概率,g[n]为在第n次之后结束的概率
设f[n]为恰好在第n次结束的概率,g[n]为在第n次之后结束的概率
显然
g
[
n
]
=
f
[
n
+
1
]
+
g
[
n
+
1
]
g[n]=f[n+1]+g[n +1]
g[n]=f[n+1]+g[n+1]
考虑生成函数,可以轻易得到
x
G
(
x
)
+
1
=
F
(
x
)
+
G
(
x
)
\large xG(x)+1=F(x)+G(x)
xG(x)+1=F(x)+G(x)
然后两边求导
G
(
x
)
+
x
G
′
(
x
)
=
F
′
(
x
)
+
G
′
(
x
)
G(x)+xG'(x)=F'(x)+G'(x)
G(x)+xG′(x)=F′(x)+G′(x)
然后把1带进去可得
F
′
(
1
)
=
G
(
1
)
F'(1)=G(1)
F′(1)=G(1)
因为概率的生成函数求导后就是期望的生成函数,所以我们实际上要求的是
F
′
(
1
)
=
G
(
1
)
\large F'(1)=G(1)
F′(1)=G(1)
考虑在当前串后面拼上一个长度为m的串,设
o
k
[
i
]
=
[
[
1...
i
]
=
[
m
−
i
+
1
,
m
]
]
ok[i]=[[1...i]=[m-i+1,m]]
ok[i]=[[1...i]=[m−i+1,m]]
G
(
x
)
×
(
1
c
x
)
m
=
∑
i
=
1
m
o
k
[
i
]
F
(
x
)
(
1
c
x
)
m
−
i
\large G(x)\times(\frac{1}{c}x)^m=\sum\limits_{i=1}^m ok[i]F(x)(\frac{1}{c}x)^{m-i}
G(x)×(c1x)m=i=1∑mok[i]F(x)(c1x)m−i
移项后可得
G
(
1
)
=
∑
i
=
1
m
o
k
[
i
]
F
(
1
)
(
c
x
)
i
G(1)=\sum\limits_{i=1}^m ok[i]F(1)(cx)^i
G(1)=i=1∑mok[i]F(1)(cx)i
然后我们注意
F
(
1
)
=
1
F(1)=1
F(1)=1所以答案就是
G
(
1
)
=
∑
i
=
1
m
o
k
[
i
]
c
i
G(1)=\sum\limits_{i=1}^m ok[i] c^i
G(1)=i=1∑mok[i]ci
code:
#include<bits/stdc++.h>
#define N 200050
#define mod 10000
using namespace std;
int qpow(int x, int y) {
int ret = 1;
for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
return ret;
}
int nxt[N], n, c, t, a[N], ha[6];
void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
for(int i = 2, j = 0; i <= n; i ++) {
while(j && a[j + 1] != a[i]) j = nxt[j];
if(a[j + 1] == a[i]) j ++;
nxt[i] = j;
}
int ans = 0;
for(int j = n; j; j = nxt[j]) ans = (ans + qpow(c, j)) % mod;
// printf("%d\n", ans);
for(int i = 1; i <= 4; i ++) ha[i] = ans % 10, ans /= 10;
for(int i = 4; i >= 1; i --) printf("%d", ha[i]); printf("\n");
}
int main() {
scanf("%d%d", &c, &t); c %= mod;
while(t --) solve();
return 0;
}