[BZOJ2160]拉拉队排练(manacher+快速幂)

来源:互联网 发布:mac下载文件夹 dock 编辑:程序博客网 时间:2024/05/03 22:29

题目描述

传送门

题解

首先求出来所有的极长回文串的长度。
然后从大到小枚举长度,用快速幂计算同一个长度的答案,然后再这些回文串加到当前长度-2的里面去。
时间复杂度O(n)

代码

#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define LL long long#define Mod 19930726#define N 2000005char a[N],s[N];int la,n,id,mx,p[N],cnt[N];LL k,ans=1;int cmp(int a,int b){    return a>b;}LL fast_pow(LL a,int p){    LL ans=1;    for (;p;p>>=1,a=a*a%Mod)        if (p&1)            ans=ans*a%Mod;    return ans;}int main(){    scanf("%d%lld\n",&n,&k);gets(a);s[0]='*';    for (int i=0;i<n;++i) s[i+1]=a[i];    for (int i=1;i<=n;++i)    {        if (mx>i) p[i]=min(p[2*id-i],mx-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;        }    }    for (int i=1;i<=n;++i) ++cnt[p[i]*2-1];    for (int i=n;i>=1;--i)        if (cnt[i])        {            if (cnt[i]<=k)            {                ans=ans*fast_pow((LL)i%Mod,cnt[i])%Mod;                if (cnt[i-2]>=0) cnt[i-2]+=cnt[i];                k-=(LL)cnt[i];            }            else            {                ans=ans*fast_pow((LL)i%Mod,k)%Mod;                k=0;                break;            }        }    if (k>0) puts("-1");    else printf("%lld\n",ans);}
0 0
原创粉丝点击