[luogu4548]歌唱王国

(可以参考hdu4652,因此推导过程比较省略)

类似的定义$f_{i}$和$g_{i}$,同样去插入$len$个字符,但注意到并不是任意一个位置都可以作为结尾,$i+j$可以作为结尾当且仅当$s[0,j)=s[len-j,j)$

令两者生成函数分别为$F(x)$和$G(x)$,则有$G(x)=sum_{iin S}m^{i}frac{F(x)}{x^{i}}$,其中$S={i|s[0,i)=s[len-i,len)}$(根据定义$lenin S$),可以通过kmp或哈希求出

答案即为$G(1)=sum_{xin S}m^{x}$,注意对10000取模以及补充前导0

 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
",ans);
25     }
26 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/14211600.html