题目传送门:https://www.luogu.org/problemnew/show/P1659
题意:
有一个长度为n的字符串,现在有一个k,求前k大的回文字串的长度的乘积。
思路:
还是比较裸的manacher。
直接打个模板跑一遍,再跑一遍倒叙循环(因为求最大)+快速幂即可。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #define LL long long #define mod 19930726 using namespace std; int n,len; LL k,ans=1; LL tot[1000010]; char s[1000010],st[2000010]; int p[2000010]; void init() { st[0]='!'; st[1]='#'; for(int i=0;i<len;i++) { st[i*2+2]=s[i]; st[i*2+3]='#'; } len=len*2+2; st[len]='@'; } void manacher() { int id=0,ma=0; for(int i=1;i<len;i++) { p[i]=ma>i?min(p[id*2-i],ma-i):1; for(;st[i+p[i]]==st[i-p[i]];p[i]++); if(ma<p[i]+i) { ma=p[i]+i; id=i; } tot[p[i]-1]+=((p[i]-1)&1); } } LL dg(LL x,LL k) { if(!k) return 1; LL t=dg(x,k>>1); return (k&1)?x%mod*t%mod*t%mod:t%mod*t%mod; } LL work() { LL sum=0; for(int i=n;i>=1;i--) if(i&1) { sum+=tot[i]; ans=ans*(k>=sum?dg(i,sum):dg(i,k))%mod; k-=sum; if(k<=0) break; } return ans; } int main() { scanf("%d %lld",&n,&k); len=n; scanf("%s",s); init(); manacher(); printf("%lld",work()); }