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

    这题的题意是 求出若干个 回文子串 按长度排序之后

    算出 (prod_{i=1}^{k} len_i)

    很显然我们可以用manacher算法 (O(n)) 求出每个回文子串的数量。但是只能求出最长的…那个

    对于每个回文的字符串(len > 2) 任意删掉两个相同的字符 还是一个回文串

    (cnt_i) 为 长度 为 i 的 回文子串的个数

    那么 (cnt_i) = (sum_{j=i}^{n}) (cnt_j)[( (j) - (i) )%2==0]

    然后考虑怎么乘起来。一个个乘显然很慢,我们计算出个数 就可以用 快速幂 直接计算这个了

    答案就是 倒序枚举 然后快速幂就可以了。

    code

    #include<bits/stdc++.h>
    using namespace std ;
    #define int long long
    #define fi first
    #define se second
    #define pb emplace_back
    inline int read() {
    	register int x = 0 , f = 1 ;
    	register char c = getchar() ;
    	for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
    	for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
    	return x * f ;
    }
    const int Mod = 19930726 ;
    template < typename T > inline bool cmax(T & x , T y) {
    	return x < y ? (x = y) , 1 : 0 ;
    }
    template < typename T > inline bool cmin(T & x , T y) {
    	return x > y ? (x = y) , 1 : 0 ;
    }
    template < typename T > inline bool cabs(T & x) {
    	return x > 0 ? 1 : (x = - x) , 0 ;
    }
    inline int QP(int x , int y , int Mod) {
    	int ans = 1 ;
    	for( ; y ; y >>= 1 , x = (x * x) % Mod)
    		if(y & 1) ans = (ans * x) % Mod ;
    	return ans ;
    }
    int n , m ;
    const int N = 11000000 + 5 ;
    char s[N] ;
    char fix[N << 2] ;
    int p[N] , ccnt[N] ;
    inline void Manacher() {
      scanf("%s" , s + 1) ;
      int cnt = 0 ;
      fix[++ cnt] = '~' ;
      fix[++ cnt] = '%' ;
      for(register int i = 1 ; i <= n ; i ++)
      fix[++ cnt] = s[i] , fix[++ cnt] = '%' ;
      int l = 0 , r = 0 , mid = 0 ;
      for(register signed i = 1 ; i <= cnt ; i ++) {
        if(i <= r) p[i] = min(p[(mid << 1) - i] , r - i + 1) ;
        while(fix[i - p[i]] == fix[i + p[i]]) ++ p[i] ;
        if(p[i] + i > r) r = p[i] + i - 1 , mid = i ;
        ccnt[p[i] - 1] ++ ;
      }
      return ;
    }
    signed main() {
      n = read() ; m = read() ;
      Manacher() ;
      for(register int i = n ; i >= 1 ; i --)
        ccnt[i] += ccnt[i + 2] ;
      int ans = 1 ;
      for(register int i = n ; i >= 1 ; i --) {
        if(! ( i & 1 )) continue ;
        if(ccnt[i] <= m) { m -= ccnt[i] ; ans = (ans * QP(i , ccnt[i] , Mod)) % Mod ; }
        else { ans = (ans * QP(i , m , Mod)) % Mod , m = 0 ; break ; }
      } printf("%lld
    " , ans ) ;
    	return 0 ;
    }
    
  • 相关阅读:
    P1007 独木桥
    P1789 【Mc生存】插火把
    P2658 汽车拉力比赛
    1959 拔河比赛
    P1936 水晶灯火灵
    websocket
    瀑布流布局
    Router
    图片占位
    单位
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/11646020.html
Copyright © 2011-2022 走看看