Jzoj1950 拉拉队排练
艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。
拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材、舞技于一体的美女从众多报名的女生中脱颖而出。这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威。
一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练。n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。
雨荨发现,如果连续的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。
现在雨荨想找出所有和谐小群体,并且按照女生的个数降序排序之后,前K个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以19930726的余数是多少就行了。
这个题也是PAM的模板题啊
跑出来以后排序让后扫一遍就好了啊
#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 1000100
#define M 19930726
#define LL long long
using namespace std;
char S[N]; LL ans=1,k;
int n,m=0,cnt=1,lst=0,v[N],r[N];
int s[N][26],f[N]={1},mx[N]={0,-1},sz[N];
inline int extend(int c){
int p=lst,np;
for(++m;S[m-mx[p]-1]!=S[m];p=f[p]);
if(!s[lst=p][c]){
np=++cnt; mx[np]=mx[p]+2;
for(p=f[p];S[m-mx[p]-1]!=S[m];p=f[p]);
f[np]=s[p][c]; lst=s[lst][c]=np;
} else lst=s[p][c]; ++sz[lst];
}
inline LL pow(LL x,LL k,LL& s){
for(;k;x=x*x%M,k>>=1) if(k&1)s=s*x%M;
}
int main(){
scanf("%d%lld%s",&n,&k,S+1);
for(int i=1;i<=n;++i) extend(S[i]-'a');
for(int i=cnt;i;--i) sz[f[i]]+=sz[i];
for(int i=2;i<=cnt;++i) ++v[mx[i]];
for(int i=*v=1;i<=n;++i) v[i]+=v[i-1];
for(int i=cnt;i>1;--i) r[v[mx[i]]--]=i;
for(int i,j=cnt;j>1;--j){
i=r[j]; if(~mx[i]&1) continue;
if(k>=sz[i]){ pow(mx[i],sz[i],ans); k-=sz[i]; }
else { pow(mx[i],k,ans); break; }
}
printf("%lld\n",ans);
}