BZOJ2160:[国家集训队2011]拉拉队排练
2160: 拉拉队排练
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1427 Solved: 576
[Submit][Status][Discuss]
Description
艾 利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长 的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材、舞技于一体的美女从众多报 名的女生中脱颖而出。这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威。一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排 练。n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。雨荨发现,如果连续 的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群 体,并且按照女生的个数降序排序之后,前K个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以19930726的余数是 多少就行了。
Input
输入为标准输入。第一行为两个正整数n和K,代表的东西在题目描述中已经叙述。接下来一行为n个字符,代表从左到右女生拿的牌子上写的字母。
Output
输出为标准输出。输出一个整数,代表题目描述中所写的乘积除以19930726的余数,如果总的和谐小群体个数小于K,输出一个整数-1。
Sample Input
5 3
ababa
ababa
Sample Output
45
【样例说明】
和谐小群体女生所拿牌子上写的字母从左到右按照女生个数降序排序后为ababa, aba, aba, bab, a, a, a, b, b,前三个长度的乘积为。
【样例说明】
和谐小群体女生所拿牌子上写的字母从左到右按照女生个数降序排序后为ababa, aba, aba, bab, a, a, a, b, b,前三个长度的乘积为。
HINT
总共20个测试点,数据范围满足:
思路{
表示被这个K的范围吓怕了。。。本来能够写出来的却吓得不敢写了。。。
然后发现只要一波快速幂就可以了。。。。。。。。。。。。。。。。。。
还是先一发回文自动机,求出每个本质不同回文串分别个数;
统计一下每个长度有多少个,枚举一下就可以了。。。。。。。
}
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf (1<<30) #define il inline #define RG register #define LL long long #define maxx 1000010 #define MOD 19930726 using namespace std;char s[maxx]; LL nxt[maxx][28],len[maxx],f[maxx],l,cc,sum[maxx],k,Ans=1,cnt[maxx]; il void Insert(RG LL n,RG LL c){ RG LL P=l;while(s[n-len[P]-1]!=s[n])P=f[P]; if(!nxt[P][c]){ len[++cc]=len[P]+2;LL pp=f[P]; while(s[n-len[pp]-1]!=s[n])pp=f[pp]; f[cc]=nxt[pp][c],nxt[P][c]=cc; }l=nxt[P][c];cnt[l]++; } il LL qpow(RG LL a,RG LL b){ if(b==1)return a%MOD;if(b==0)return 1; RG LL tmp=(qpow(a,(b>>1))+MOD)%MOD; tmp=(tmp*tmp+MOD)%MOD; if(b&1)tmp=(tmp*((a+MOD)%MOD)+MOD)%MOD; return tmp; } void count(){for(RG LL i=cc;i!=1;i--)cnt[f[i]]+=cnt[i];for(RG LL i=cc;i!=1;i--)sum[len[i]]+=cnt[i];} il void work(){ LL LEN;scanf("%lld%lld",&LEN,&k);f[0]=1,len[++cc]=-1; scanf("%s",s+1);for(RG LL i=1;i<=LEN;++i)Insert(i,s[i]-'a'+1); count();LL N=LEN%2==0?--LEN:LEN; for(LL i=N;k>0&&i>0;i-=2) if(sum[i]) Ans*=qpow(i,min(sum[i],k)),Ans%=MOD,k-=min(sum[i],k); if(k>0)cout<<"-1";else cout<<Ans; } int main(){ work();return 0; }