luogu P1659 [国家集训队]拉拉队排练

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

猜你喜欢

转载自blog.csdn.net/zsyz_zzy/article/details/80106657