【马拉车manacher】奇长回文(2022.5.21)

上题目!

题目

3.1 题目描述

给定一个长为 L 的仅含小写字母的字符串,需要在其奇数长度的回文子串中找到最长的 k 个,并且输出它们长度的乘积对19961202 取模的值,若奇数长度的回文子串不足 k 个则输出-1 。

3.2 输入格式

第一行两个整数L, k,如题意所述;
接下来一行为一个长为 L 的字符串。

3.3 输出格式

输出一行一个整数,表示答案。

3.4 样例输入

5 3
ababa 

3.5 样例输出

45 

3 .6 样例解释

奇数长度的回文子串有:ababa, aba, aba, bab, a, a, a, b, b,最长的三个长度分别为 5, 3, 3,故乘积为 533=45

3 .7 数据范围与约定

对于前20%的数据,L, k≤100;
对于另外20%的数据,k=1;
对于100%的数据,1≤L≤106, 1≤k≤1012

解思

马拉车裸题,甚至都不需要在字符中间加&,跑出以每个点为中心的最大奇长回文串后从大往小累加计算,再跑快速幂即可

long long乘爆的人就是屑

代码如下:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
	int f=1,j=0;char w=getchar();
	while(w>'9'|w<'0'){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(w>='0'&&w<='9'){
		j=(j<<3)+(j<<1)+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=1000010,mod=19961202;
char s[N];
int tong[N],n,k,f[N],sum,maxn,ans=1;
int mi(int x,int y){
	int nown=x,ansn=1;
	while(y>0){
		if(y&1)ansn=ansn*nown%mod;
		nown=nown*nown%mod;
		y/=2;
	}
	return ansn;
}
signed main(){
	//freopen("odd.in","r",stdin);
	//freopen("odd.out","w",stdout);
	n=read();k=read();
	scanf("%s",s+1);
	int r=0,mid=0;
	for(int i=1;i<=n;i++){
		if(i>r){
			int len=0;
			while(i-len-1>0&&i+len+1<=n&&s[i-len-1]==s[i+len+1])len++;
			f[i]=len;
			mid=i;r=i+len;
		}
		else{
			int len=f[mid*2-i];
			if(len<r-i)f[i]=len;
			else{
				len=min(r-i,len);
				while(i-len-1>0&&i+len+1<=n&&s[i-len-1]==s[i+len+1])len++;
				if(i+len>r){
					mid=i;
					r=i+len;
				}
				f[i]=len;
			}
		}
		tong[f[i]]++;
		maxn=max(f[i],maxn);
		sum+=f[i]+1;
	}
	if(sum<k){
		printf("-1");
		return 0;
	}
	int nown=0;
	for(int i=maxn;i>=1&&k!=0;i--){
		nown+=tong[i];
		if(nown>=k){
			ans=ans*mi(i*2+1,k)%mod;
			break;
		}
		else{
			k-=nown;
			ans=ans*mi(i*2+1,nown)%mod;
		}
	}
	printf("%d",ans);
	return 0;
}
/*
5 3
ababa
*/
posted @   flywatre  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示