BZOJ2160 拉拉隊排練題解(manacher)
阿新 • • 發佈:2019-01-13
題目:BZOJ2160.
題目大意:給定一個字串,求它所有長度為奇數的迴文子串中,前k小的長度乘積.若數量超過k輸出-1.
一看就是道manacher裸題,由於長度要求為奇數,所以就不需要在字串中間插入奇奇怪怪的字元啦,只需要在兩邊插入不一樣的字元就可以了.
我們再設一個數組cnt[i]表示長度為i的迴文子串有多少個,那麼每得到一個新的最長迴文子串長度pal[i]我們就可以將1~pal[i]的所有cnt值都加1,但是這樣太慢了所以我們差分一下.
最後我們從1開始列舉,每次加2.當列舉到i時得到的貢獻為 ,快速冪搞一下就可以了.
程式碼如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=1000000;
const LL mod=19930726;
int pal[N+9];
void manacher(char *s,int len){
s[len+1]='#';
int p=0,r=0;
pal[0]=1;
for (int i=1;i<=len;++i){
pal[i]=i< r?min(pal[2*p-i],r-i):1;
while (s[i+pal[i]]==s[i-pal[i]]) ++pal[i];
if (i+pal[i]>r) r=i+pal[i],p=i;
}
}
int cnt[N+9];
LL power(LL a,LL k){
LL s=1;
for (;k;k>>=1,a=a*a%mod)
if (k&1) s=s*a%mod;
return s;
}
char c[N+9];
int n;
LL k,ans=1;
void js(){
for (int i=1;i<=n;++i)
++cnt[1],--cnt[pal[i]<<1];
for (int i=1;i<=n;++i)
cnt[i]+=cnt[i-1];
for (int i=n;i>=1;--i){
if (i&1^1) continue;
if (cnt[i]>=k){
ans=ans*power(LL(i),k)%mod;k=0;
break;
}else ans=ans*power(LL(i),LL(cnt[i]))%mod,k-=LL(cnt[i]);
}
if (k) ans=-1LL;
}
Abigail into(){
scanf("%d%lld",&n,&k);
scanf("%s",c+1);
}
Abigail work(){
manacher(c,n);
js();
}
Abigail outo(){
printf("%lld",ans);
}
int main(){
into();
work();
outo();
return 0;
}