• [ BZOJ 2160 ] 拉拉队排练


    (\)

    (Description)


    一个由小写字母构成的长为(N)的字符串,求前(K)长的奇数长度回文子串长度之积,对(19930726)取模后的答案。

    • (Nin [1,10^6])(Kin [1,10^{12}])

    (\)

    (Solution)


    • (Manacher)处理出所有位置的回文半径,因为答案要求奇数长度,所以不用插入特殊字符,在原串上直接跑(Manacher)就好,回文半径内的以当前点为回文中心的每一个子串都是回文串。
    • 所以开一个长度的桶,只给回文半径对应的最长子串长度打标记,显然一个标记代表着后面所有位置都(+1),所以计算的时候,一个长度的回文子串个数是长度标记的前缀和。
    • 要求的(K)非常大,快速幂处理。

    (\)

    (Code)


    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 1000010
    #define R register
    #define gc getchar
    #define mod 19930726
    using namespace std;
    typedef long long ll;
     
    char c,s[N];
     
    ll m,res=1,sum;
     
    int n,len[N],cnt[N];
     
    inline void init(){
      scanf("%d%lld",&n,&m);
      while(!isalpha(c=gc()));
      s[1]=c; s[0]='['; s[n+1]=']';
      for(R int i=2;i<=n;++i) s[i]=gc();
    }
     
    inline void manacher(){
      for(R int i=1,p=0,mr=0;i<=n;++i){
        len[i]=i>mr?1:min(mr-i+1,len[(p<<1)-i]);
        while(s[i-len[i]]==s[i+len[i]]) ++len[i];
        if(i+len[i]-1>mr){p=i;mr=i+len[i]-1;}
        ++cnt[(len[i]<<1)-1];
      }
    }
     
    inline ll qpow(ll x,ll t){
      ll res=1;
      while(t){
        if(t&1) (res*=x)%=mod;
        (x*=x)%=mod; t>>=1;
      }
      return res;
    }
     
    int main(){
      init();
      manacher();
      for(R int i=((n/2)<<1)+1;i>=1;i-=2){
        sum+=(ll)cnt[i];
        if(sum>=m){printf("%lld",(res*qpow(i,m))%mod);return 0;}
        (res*=qpow(i,sum))%=mod; m-=sum;
      }
      puts("-1");
      return 0;
    }
    
  • 相关阅读:
    路由器端口映射
    字符编码笔记:ASCII,Unicode和UTF-8
    2、Spring之AOP
    八、模板方法模式
    三、装饰者模式
    七、适配器模式
    六、命令模式
    五、单件模式
    乐观锁与悲观锁——解决并发问题
    一、策略模式
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9690070.html
Copyright © 2020-2023  润新知