版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/86312762
题目: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;
}