BZOJ2160 拉拉队排练题解(manacher)

版权声明:转载请注明原出处啦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时得到的贡献为 i c n t [ i ] i^{cnt[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;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/86312762
今日推荐