zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    70     return 0;
    71 }
  • 相关阅读:
    摒弃FORM表单上传图片,异步批量上传照片
    小功能——简单代码实现邮箱发送邮件
    小工具 ——快速生成验证码
    [转]C++11 多线程
    [转]线性插值&双线性插值&三线性插值
    [转]第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV
    windows的Timer和写文件方式串口注意!
    OPENCV3.1+VS 坑我笔记!
    最简单的PC机串口通信程序
    用MFC时,如果程序崩溃,检查内存,然后注意GDI数量,在任务管理器里选项-查看列-GDI数量
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9676519.html
Copyright © 2011-2022 走看看