bzoj2160 拉拉队排练 manacher+差分

本文介绍了一种使用Manacher算法寻找字符串中的回文子串的方法,特别关注于奇数长度的回文串,并通过快速幂计算特定条件下回文串数量的乘积。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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 19930726
using 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值