题目传送门: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());
}