[luogu4548]歌唱王国
记$g_{i}$表示长度为$i$且不存在$s$的字符串数量$,f_{i}$表示仅在末尾出现$s$的字符串数量
对所有满足$g_{i}$中性质的字符串末尾加上$s$,显然上述字符串仍有$g_{i}$个
另一方面,枚举其中第一次出现$s$的位置$i+l$,对应的字符串恰有$f_{i+l}$个
同时,$s[1,l]$必须是$s$的border,最终得到$g_{i}=\sum_{s[1,l]是s的border}f_{i+l}$
记$G(x)=\sum_{i\ge 0}\frac{g_{i}}{m^{i}}x^{i},F(x)=\sum_{i\ge 0}\frac{f_{i}}{m^{i}}x^{i}$,代入上式即
$$
G(x)=\sum_{i\ge 0}\frac{g_{i}}{m^{i}}x^{i}=\sum_{i\ge 0}\sum_{s[1,l]是s的border}\frac{m^{l}f_{i+l}}{m^{i+l}}x^{i}=\sum_{s[1,l]是s的border}\frac{m^{l}F(x)}{x^{l}}
$$
注意到$\frac{g_{i}}{m^{i}}$即为答案$>i$的概率,进而$G(1)$即为答案的期望
同时,注意到$\frac{f_{i}}{x^{i}}$即为答案$=i$的概率,因此$F(1)=1$,代入上式即$G(1)=\sum_{s[1,l]是s的border}m^{l}$
求出$s$的border使用KMP/二分+哈希即可,时间复杂度为$o(n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define mod 10000 5 int n,m,t,ans,a[N],mi[N],nex[N]; 6 int main(){ 7 scanf("%d%d",&m,&t); 8 mi[0]=1; 9 for(int i=1;i<N-4;i++)mi[i]=1LL*mi[i-1]*m%mod; 10 while (t--){ 11 scanf("%d",&n); 12 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 13 nex[0]=nex[1]=0; 14 for(int i=2,j=0;i<=n;i++){ 15 while ((j)&&(a[i]!=a[j+1]))j=nex[j]; 16 if (a[i]==a[j+1])j++; 17 nex[i]=j; 18 } 19 ans=0; 20 for(int i=n;i;i=nex[i])ans=(ans+mi[i])%mod; 21 if (ans<10)printf("0"); 22 if (ans<100)printf("0"); 23 if (ans<1000)printf("0"); 24 printf("%d\n",ans); 25 } 26 }