[国家集训队]拉拉队训练

Manacher的题,较简单。
先manacher一下,找到每个回文串的长度,把长度为奇数的回文串统计一下,由于manacher,每个字母只会被统计一次,就不存在重复计算。看那个数据范围里面巨大的K很唬人,但是复杂度和这个K关系不大。(奇丑无比堪比wwb的代码)

//Writer : Hsz %WJMZBMR%tourist%hzwer
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <cstdlib>
#include <algorithm>
#define LL long long
#define M(a,b) memset(a,b,sizeof a)
const int inf=0x3fffffff;
using namespace std;
const double eps=1e-8;
int read() {
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}
void out(int x) {
	int a[25],wei=0;
	if(x<0) putchar('-'),x=-x;
	for(; x; x/=10) a[++wei]=x%10;
	if(wei==0) {
		puts("0");
		return;
	}
	for(int j=wei; j>=1; --j) putchar('0'+a[j]);
	putchar('
');
}
const int N=2000005,mod=19930726;
char a[N>>1],s[N];
int len,p[N],mx,id,cnt[N];
LL n,k;
void manacher() {
	for(int i=1; i<len; i++) {
		if(i<mx) p[i]=min(p[id]+id-i,p[id*2-i]);
		else p[i]=1;
		while(s[i+p[i]]==s[i-p[i]]) p[i]++;
		if(i+p[i]>mx) mx=i+p[i],id=i;
		if((p[i]-1)&1) cnt[p[i]-1]++;
	}
}
LL ksm(LL base,int z) {
	if(base==1)return 1;
	if(!z) return 1;
	LL res=1;
	while(z) {
		if(z&1) res*=base,res%=mod;
		base*=base,base%=mod;
		z>>=1;
	}
	return res;
}
int main() {
	cin>>n>>k;
	scanf("%s",a);
	len=n;
	s[0]=s[1]='!';
	for(int i=0; i<len; i++) {
		s[i*2+2]=a[i];
		s[i*2+3]='!';
	}
	len=len*2+2;
	s[len]=0;
	manacher();
	LL sum=0;
	LL ans=1;
	for(int i=n-1+(n&1); i; i-=2) {
		sum+=cnt[i];
		if(k>=sum) {
			ans=(ans*ksm(i,sum))%mod;
			k-=sum;
		} else {
			ans=(ans*ksm(i,k))%mod;
			k-=sum;
			break;
		}
	}
	cout<<ans;
	return 0;
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9264991.html