首先容斥一下,统计不合法方案
对S建出KMP自动机,则答案显然是走m步走出一个环的方案,枚举起点pos,直接dp可以获得60分
注意到一个点指向非根节点的出边是唯一的,不然就无法满足字典序的要求,所以可以枚举走到根节点的时刻再dp
预处理dp数组
f
[
i
]
[
j
]
f[i][j]
f[i][j]为
i
i
i步走到
j
j
j的方案数
Code:
#include<bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
inline int add(int a,int b){a+=b;if(a>=mod) a-=mod;return a;}
inline int dec(int a,int b){a-=b;if(a<0) a+=mod;return a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void inc(int &a,int b){a+=b;if(a>=mod) a-=mod;}
inline int ksm(int a,int b){int res=1;for(;b;b>>=1,a=mul(a,a)) if(b&1) res=mul(res,a);return res;}
const int N=2e3+5;
int n,m,nxt[N],pos[N],dp[N][N];
char s[N];
inline void kmp(){
pos[0]=1;
for(int i=1;i<=n;i++){
int j=nxt[i-1];
while(j && s[j+1]!=s[i]) j=nxt[j];
if(s[j+1]==s[i] && i!=1) ++j;
nxt[i]=j;pos[i]=pos[j];
if(s[i+1]>=s[pos[j]]) pos[i]=i+1;
}
}
inline void Dp(){
dp[0][0]=1;
for(int i=1;i<=m;i++)
for(int j=0;j<=n;j++){
inc(dp[i][pos[j]],dp[i-1][j]);
inc(dp[i][0],mul(dp[i-1][j],('z'-s[pos[j]])));
}
}
inline int get_ans(){
int res=0;
for(int i=0;i<=n;i++){
int p=i;
for(int j=0;j<m;j++){
if(p==0){inc(res,dp[m-j][i]);break;}
inc(res,mul(dp[m-j-1][i],'z'-s[pos[p]]));
p=pos[p];
if(j==m-1 && p==i) inc(res,1);
}
}
return res;
}
int main(){
m=read();scanf("%s",s+1);n=strlen(s+1);
kmp();Dp();
cout<<dec(ksm(26,m),get_ans());
return 0;
}