BZOJ 2160: 拉拉队排练
Description
问长度前 \(k\) 大的奇长度回文子串的乘积.
Sol
Manacher.
直接马拉车跑一边,统计一下答案,每次将长度-2就可以了.
Code
/************************************************************** Problem: 2160 User: BeiYu Language: C++ Result: Accepted Time:288 ms Memory:36456 kb ****************************************************************/ #include <cstdio> #include <iostream> using namespace std; typedef long long LL; const int N = 2000500; const LL p = 19930726; LL n,k,st,ans=1; LL f[N],c[N]; char ch[N],s[N]; LL Pow(LL a,LL b,LL r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; } int main() { cin>>n>>k; scanf("%s",s+1); s[0]='$'; for(LL i=1,mx=0,j=0;i<=n;i++) { if(mx>i) f[i]=min(f[2*j-i],mx-i);else f[i]=1; for(;s[i+f[i]] == s[i-f[i]];f[i]++); if(i+f[i]>mx) mx=i+f[i],j=i; } for(int i=1;i<=n;i++) c[f[i]*2-1]++,st=max(st,f[i]*2-1); // for(int i=0;i<=n;i++) putchar(s[i]);cout<<endl; // for(int i=0;i<=n;i++) cout<<f[i]<<" ";cout<<endl; // for(int i=0;i<=st;i++) cout<<c[i]<<" ";cout<<endl; for(LL t;st;st--) { t=min(c[st],k); ans=(ans*Pow(st,t))%p; k-=t; if(st-2>0) c[st-2]+=c[st]; if(!k) break; } if(k) puts("-1"); else cout<<ans<<endl; return 0; }