[BZOJ 2160]拉拉队排练

一、题目

点此看题

二、解法

求前 k k k大的奇数回文子串,我们先跑一遍马拉车,然后差分算出每个长度的回文串,快速幂就可做了。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 2000005;
const int MOD = 19930726;
#define ll long long
#define int long long
int read()
{
    int x=0,flag=1;char c;
    while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
    while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*flag;
}
int n,k,l[M],cnt[M];char s[M],t[M];
ll qkpow(ll a,int b)
{
    ll res=1;
    while(b>0)
    {
        if(b&1) res=res*a%MOD;
        a=a*a%MOD;
        b>>=1;
    }
    return res;
}
signed main()
{
    n=read();k=read();
    scanf("%s",s);
    for(int i=0;i<n;i++)
    {
        t[2*i+1]=s[i];
        t[2*i]='#';
    }
    t[2*n]='#';
    n=2*n+1;
    int c=0,r=0,ans=0;
    for(int i=0;i<n;i++)
    {
        l[i]=r>i?min(l[2*c-i],r-i+1):1;
        while(i+l[i]<n && i-l[i]>=0 && t[i+l[i]]==t[i-l[i]])
            l[i]++;
        if(i+l[i]>r)
        {
            r=i+l[i]-1;
            c=i;
        }
        ans=max(ans,l[i]);
    }
    for(int i=1;i<n;i+=2)
    {
        cnt[1]++;cnt[l[i]+1]--;
    }
    for(int i=3;i<n;i+=2)
    {
        cnt[i]+=cnt[i-2];
    }
    ll mul=1;
    for(int i=n-2;i>0;i-=2)
    {
        if(k>=cnt[i])
        {
            mul=mul*qkpow(i,cnt[i])%MOD;
            k-=cnt[i];
        }
        else
        {
            mul=mul*qkpow(i,k)%MOD;
            k=0;
            break;
        }
    }
    if(k) puts("-1");
    else printf("%lld\n",mul);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值