zoukankan      html  css  js  c++  java
  • [国家集训队]拉拉队排练

    题意

    将给定字符串S的奇数长度回文串按长度排序,求前k长的回文子串长度乘积,对19930726取模。

    对于100%的数据n<=1e6,k<=1e12

    题解

    若有长度为i的回文子串,就有长度为i-2的回文子串;

    manacher求的是以一个点为中心的最长回文子串,当求到一个长度为len(奇数)的子串,就得到1,3,...len的回文子串,考虑差分。

    先预处理出长度为i的回文子串的个数(长度不超过n),倒着遍历数组,统计答案,用快速幂。

    没什么本质难度,主要在于第一步的性质和差分。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    const int maxn=2000005;
    const int mod=19930726;
    int n;
    ll k,ans=1;
    char s[maxn],t[maxn];
    int pl[maxn];
    int cx[maxn];//存长度为i的回文串有几个
    
    ll fast_pow(ll a,ll b){
        ll ret=1;
        while(b){
            if(b&1) ret=ret*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return ret;
    }
    
    void manacher(){
        s[0]='+';
        for(int i=1;i<2*n;i+=2){
            s[i]='#';
            s[i+1]=t[i/2];
        }
        s[2*n+1]='#';
        s[2*n+2]='-';
        s[2*n+3]='';
        int mx=0,id=0;
        n=2*n+1;
        for(int i=1;i<=n;i++){
            if(mx>=i) pl[i]=min(mx-i+1,pl[2*id-i]);
            else pl[i]=1;
            while(s[i+pl[i]]==s[i-pl[i]]) pl[i]++;
            if(mx<i+pl[i]-1) mx=i+pl[i]-1,id=i;
            if(i&1) continue;
            cx[1]++;cx[pl[i]]--;
        }
    }
    
    int main(){
        scanf("%d%lld%s",&n,&k,t);
        manacher();
        for(int i=1;i<=n;i++) cx[i]+=cx[i-1];
        //for(int i=1;i<=n;i++) printf("%d ",cx[i]);
        for(int i=n;i>=0&&k;i-=2)
         if(cx[i]){
             if(cx[i]>=k) ans=ans*fast_pow(i,k)%mod,k=0;
             else ans=ans*fast_pow(i,cx[i])%mod,k-=cx[i];
        }
        if(k) printf("-1");
        else printf("%lld",ans);
    } 
    View Code
  • 相关阅读:
    vector容器(一)
    螺旋数组实现
    zigzag数组实现
    HDU 1496
    HDU 1381 Crazy Search
    什么叫软核,固核,硬核?
    “杜拉拉思维模式”之六:小组面试提升术
    硬件工程师电路设计必须紧记的十大要点
    面试的“群殴”宝典
    三段式状态机 [CPLD/FPGA]
  • 原文地址:https://www.cnblogs.com/sto324/p/11228045.html
Copyright © 2011-2022 走看看