bzoj2160 拉拉队排练 manacher+差分

来源:互联网 发布:银行存款怎样划算知乎 编辑:程序博客网 时间:2024/05/16 04:37

/ * 先来一波像题面一样辣眼睛的骚粉色 * /

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

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

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

Sample Input
5 3
ababa

WA点

啊这道题真是气哭,wa了半天最后发现时long long 的问题。
先复习一下基础知识:
unsigned int 0~4294967295
int 2147483648~2147483647
unsigned long 0~4294967295
long 2147483648~2147483647
long long的最大值:9223372036854775807
long long的最小值:-9223372036854775808
unsigned long long的最大值:1844674407370955161
__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615

按理说这道题除k以外不会爆int 啊,不懂不懂,反正以后看着数大就开long long吧(好草率)

思路

先来一波manacher,这道题只要求奇数所以在字符串中不用插入‘#’,再用差分统计出每种长度的回文串个数。要注意回文串的长度为奇数所以

if(i%2&&sum[i])

要判断i%2
最后统计的时候记得用快速幂

代码:

/****************************************************    Problem: 2160    User: DD_D    Language: C++    Result: Accepted    Time:260 ms    Memory:13516 kb*****************************************************/#include<cstdio>#include<cstring>#define ll long long#define MOD 19930726using namespace std;const int N=1e6+5;ll k,sum[N];int n,pal[N],len;char s[N];int min(int a,int b){    return a<b?a:b;}int max(int a,int b){    return a>b?a:b;}void manacher(){    int mx=0,id;    for(int i=1;i<=len;i++){        if(mx>=i) pal[i]=min(mx-i+1,pal[2*id-i]);        else pal[i]=1;        while(s[i-pal[i]]==s[i+pal[i]]) pal[i]++;        if(pal[i]+i-1>mx) mx=i+pal[i]-1,id=i;        sum[0]++,sum[2*pal[i]]--;    }}ll pow(ll x,ll y)//xy次方 {    ll base=x,ans=1;    for(ll i=y;i;i>>=1,base=(base*base)%MOD)    if(i&1) ans=(ans*base)%MOD;    return ans%MOD;}int main(){    ll ans=1;    scanf("%d%lld",&n,&k);    scanf("%s",s+1);    len=strlen(s+1);    s[0]='+',s[++len]='-';    manacher();    for(int i=1;i<=n+1;i++) sum[i]+=sum[i-1];    for(int i=n;i>=1;i--){        if(i%2&&sum[i])        if(k-sum[i]>=1) ans=(ans*pow(i,sum[i]))%MOD,k-=sum[i];        else {            ans=(ans*pow(i,k))%MOD,k-=sum[i];k=0;break;        }    }    printf("%d",k?-1:ans);    return 0;}
原创粉丝点击