题:https://www.luogu.com.cn/problem/P1659
题意:问前k大的奇数长度的回文串的长度乘积;
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int M=1e6+6; const int maxn=26; const int mod=19930726; char s[M]; struct node{ ll val,num; bool operator<(const node &b)const{ return val>b.val; } }b[M]; struct pam{ int son[M][maxn],cnt[M],num[M],fail[M],len[M]; char s[M]; int tot,last; int newnode(int Len){ for(int i=0;i<maxn;i++) son[tot][i]=0; cnt[tot]=0; num[tot]=0; fail[tot]=0; len[tot]=Len; return tot++; } void init(){ s[0]='#'; tot=0; last=0; newnode(0); newnode(-1); fail[0]=1; } int getfail(int p,int i){ while(s[i-len[p]-1]!=s[i]) p=fail[p]; return p; } void solve(const char *buf){ init(); int n=strlen(buf+1); for(int i=1;i<=n;i++){ s[i]=buf[i]-'a'; int cur=getfail(last,i); if(!son[cur][s[i]]){ int now=newnode(len[cur]+2); fail[now]=son[getfail(fail[cur],i)][s[i]]; son[cur][s[i]]=now; num[now]=num[fail[now]]++; } cnt[last=son[cur][s[i]]]++; } for(int i=tot-1;i>=0;i--) cnt[fail[i]]+=cnt[i]; } }PAM; ll ksm(ll a,ll b){ ll t=1ll; while(b){ if(b&1){ t=(t*a)%mod; } b>>=1ll; a=(a*a)%mod; } return t; } int main(){ ll n,k; scanf("%lld%lld",&n,&k); scanf("%s",s+1); PAM.solve(s); int m=0; for(int i=0;i<PAM.tot;i++){ // cout<<PAM.len[i]<<"!!"<<PAM.cnt[i]<<endl; if(PAM.len[i]&1){ b[m].val=PAM.len[i]; b[m].num=PAM.cnt[i]; m++; } } sort(b,b+m); ll ans=1ll; for(int i=0;i<m;i++){ ans=(1ll*ans*ksm(b[i].val,min(1ll*b[i].num,k)))%mod; // cout<<ans<<endl; k-=b[i].num; if(k<=0) break; } printf("%lld\n",ans); return 0; }View Code