BZOJ2160: 拉拉队排练(Manacher)

Description

艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材、舞技于一体的美女从众多报名的女生中脱颖而出。这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威。一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练。n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。雨荨发现,如果连续的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群体,并且按照女生的个数降序排序之后,前K个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以19930726的余数是多少就行了。

Input

输入为标准输入。第一行为两个正整数n和K,代表的东西在题目描述中已经叙述。接下来一行为n个字符,代表从左到右女生拿的牌子上写的字母。

Output

输出为标准输出。输出一个整数,代表题目描述中所写的乘积除以19930726的余数,如果总的和谐小群体个数小于K,输出一个整数-1。

Sample Input

5 3
ababa

解题思路:

第一眼看到k<=1000,000,000,000懵逼了,回文串怎么会有这么多。

结果再看一眼题才知道这个回文串是可以居于其他回文串正中间的,那就和平了。

先Manacher求出以每个点为中间的最长回文串长度放入桶中。

很显然以 i最长奇数长的最长回文串长为 l 有 x 个,那么 l-2 也有 x 个。

快速幂一下就好了^_^

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using std::min;
 5 typedef long long lnt;
 6 const lnt mod=19930726;
 7 char a[2000000];
 8 int l[3000000];
 9 int f[3000000];
10 int s[2000000];
11 int cnt;
12 int n;
13 lnt k;
14 lnt ans;
15 lnt Qpw(lnt x,lnt y)
16 {
17     lnt ans=1;
18     while(y)
19     {
20         if(y&1)
21             ans=ans*x%mod;
22         x=x*x%mod;
23         y/=2;
24     }
25     return ans;
26 }
27 int main()
28 {
29     scanf("%d%lld",&n,&k);
30     scanf("%s",a+1);
31     l[cnt]='@';
32     for(int i=1;i<=n;i++)
33     {
34         l[++cnt]='@';
35         l[++cnt]=a[i];
36     }
37     l[++cnt]='@';
38     int mx=1;
39     f[1]=1;
40     for(int i=2;i<=cnt;i++)
41     {
42         f[i]=min(f[mx*2-i],f[mx]+mx-i);
43         while(f[i]+i<=cnt&&l[f[i]+i]==l[i-f[i]])
44             f[i]++;
45         if(mx+f[mx]<f[i]+i)
46             mx=i;
47         if((f[i]-1)&1)
48             s[f[i]-1]++;
49     }
50     ans=1;
51     lnt sum=0;
52     for(int i=n;i>=1;i--)
53     {
54         if(i%2==0)
55             continue;
56         sum+=s[i];
57         if(k>sum)
58         {
59             ans=ans*Qpw(i,sum)%mod;
60             k-=sum;
61         }else{
62             ans=ans*Qpw(i,k)%mod;
63             k-=sum;
64             break;
65         }
66     }
67     if(k>0)
68         ans=-1;
69     printf("%lld\n",ans);
70     return 0;
71 }

 

posted @ 2018-09-19 19:26  Unstoppable728  阅读(139)  评论(0编辑  收藏  举报