Jzoj1950 拉拉队排练

227 篇文章 3 订阅
134 篇文章 0 订阅

艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。
  拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值