[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 }
View Code

 

posted @ 2020-12-30 15:17  PYWBKTDA  阅读(96)  评论(0编辑  收藏  举报