• [国家集训队]拉拉队排练


    嘟嘟嘟

    看到回文串,就想到了manacher。而且这道题只用求长度为奇数的回文串,所以不用添加字符,在原回文串上跑一边即可。

    需要注意的是,如果一个回文串的半径是r,那么这个回文串同时也包含了r - 1, r - 2,……1的回文串,因为r表示的是以 i 为回文中心的最长的回文串。于是我们开一个桶,记录回文半径长度为 i 的回文串有多少个,用前缀和的思想,差分维护区间加1。最后倒着扫一边,快速幂加速乘法。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const int maxn = 1e6 + 5;
    21 const ll mod = 19930726;
    22 inline ll read()
    23 {
    24   ll ans = 0;
    25   char ch = getchar(), last = ' ';
    26   while(!isdigit(ch)) {last = ch; ch = getchar();}
    27   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    28   if(last == '-') ans = -ans;
    29   return ans;
    30 }
    31 inline void write(ll x)
    32 {
    33   if(x < 0) x = -x, putchar('-');
    34   if(x >= 10) write(x / 10);
    35   putchar(x % 10 + '0');
    36 }
    37 
    38 int n;
    39 ll k;
    40 char s[maxn];
    41 int r[maxn];
    42 
    43 void manacher()
    44 {
    45   s[0] = '@'; s[n + 1] = '$';
    46   int mx = 0, id;
    47   for(int i = 1; i <= n; ++i)
    48     {
    49       if(i < mx) r[i] = min(r[(id << 1) - i], mx - i);
    50       else r[i] = 1;
    51       while(s[i - r[i]] == s[i + r[i]]) r[i]++;
    52       if(i + r[i] > mx) mx = i + r[i], id = i;
    53     }
    54 }
    55 
    56 ll dif[maxn];
    57 ll ans = 1;
    58 
    59 ll quickpow(ll a, ll b)
    60 {
    61   a %= mod;
    62   ll ret = 1;
    63   while(b)
    64     {
    65       if(b & 1) ret = ret * a % mod;
    66       a = a * a % mod; b >>= 1;
    67     }
    68   return ret;
    69 }
    70 
    71 int main()
    72 {
    73   n = read(); k = read(); scanf("%s", s + 1);
    74   manacher();
    75   for(int i = 1; i <= n; ++i) dif[1]++, dif[r[i] + 1]--;
    76   for(int i = 1; i <= n; ++i) dif[i] = dif[i - 1] + dif[i];
    77   for(int i = (n + 1) >> 1; i; --i)
    78     {
    79       if(k - dif[i] > 0)
    80     {
    81       k -= dif[i];
    82       ans *= quickpow((i << 1) - 1, dif[i]);
    83       ans %= mod;
    84     }
    85       else
    86     {
    87       ans *= quickpow((i << 1) - 1, k);
    88       ans %= mod;
    89       k = 0; break;
    90     }
    91     }
    92   write(k ? -1 : ans); enter;
    93   return 0;
    94 }
    View Code
  • 相关阅读:
    C++ 递归读取目录下所有文件
    C++ XML文件解析
    常用数据结构之栈
    常用数据结构之队列
    通过shell快速配置J2EE运行环境
    docker:(5)利用docker -v 和 Publish over SSH插件实现war包自动部署到docker
    docker:(4)利用WebHook实现持续集成
    docker:(3)docker容器挂载宿主主机目录
    docker:(2)通过Dockerfile构建镜像并发布web项目
    docker:(1)docker基本命令使用及发布镜像
  • 原文地址:https://www.cnblogs.com/mrclr/p/9796056.html
Copyright © 2020-2023  润新知