嘟嘟嘟




方案:回文子序列数 - 回文子串数。

回文子串数用manacher解决就行了,关键是怎么求会问序列数。

一个比较好的\(O(n ^ 2)\)的算法:对于一个回文中心\(i\),\(O(n)\)求出以\(i\)为中心位置对称且字母相同的字母对数\(x\),则以\(i\)为回文中心的回文子序列有\(2 ^ x - 1\)个(排除空序列)。

现在想一下怎么优化。

上面寻找的过程,用一个式子写出来就是这样:

\[c(i) = \sum _ {j = 0} ^ {i} s[i - j] == s[i + j]
\]

会发现这东西和卷积特别像,但是怎么用多项式表示\(s[i - j] == s[i + j]\)呢?

因为题中说了只有\(a, b\)两种字母,所以构造两个只有\(0\)或\(1\)的多项式\(A, B\),如果\(s[i] = 'a'\),那么\(A(i) = 1\);\(B\)同理。

这样的话式子就变成了

\[c(i) = \sum_{j = 0} ^ {i} A(i - j) * A(i + j) + \sum _ {j = 0} ^ {i} B(i - j) * B(i + j) - 1
\]

然后两次卷积就行啦。




fft还是不熟……

  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 db PI = acos(-1);
  21. const int maxn = 8e5 + 5;
  22. const ll mod = 1e9 + 7;
  23. inline ll read()
  24. {
  25. ll ans = 0;
  26. char ch = getchar(), last = ' ';
  27. while(!isdigit(ch)) last = ch, ch = getchar();
  28. while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  29. if(last == '-') ans = -ans;
  30. return ans;
  31. }
  32. inline void write(ll x)
  33. {
  34. if(x < 0) x = -x, putchar('-');
  35. if(x >= 10) write(x / 10);
  36. putchar(x % 10 + '0');
  37. }
  38. int n, len = 1;
  39. char s[maxn];
  40. struct Comp
  41. {
  42. db x, y;
  43. inline Comp operator + (const Comp& oth)const
  44. {
  45. return (Comp) {x + oth.x, y + oth.y};
  46. }
  47. inline Comp operator - (const Comp& oth)const
  48. {
  49. return (Comp){x - oth.x, y - oth.y};
  50. }
  51. inline Comp operator * (const Comp& oth)const
  52. {
  53. return (Comp){x * oth.x - y * oth.y, x * oth.y + oth.x * y};
  54. }
  55. friend inline void swap(Comp& a, Comp& b)
  56. {
  57. swap(a.x, b.x); swap(a.y, b.y);
  58. }
  59. }a[maxn], b[maxn], omg[maxn], inv[maxn];
  60. void init()
  61. {
  62. omg[0] = inv[0] = (Comp){1, 0};
  63. omg[1] = inv[len - 1] = (Comp){cos(2 * PI / len), sin(2 * PI / len)};
  64. for(int i = 2; i < len; ++i) omg[i] = inv[len - i] = omg[i - 1] * omg[1];
  65. }
  66. void fft(Comp* a, Comp* omg)
  67. {
  68. int lim = 0;
  69. while((1 << lim) < len) lim++;
  70. for(int i = 0; i < len; ++i)
  71. {
  72. int t = 0;
  73. for(int j = 0; j < lim; ++j) if((i >> j) & 1) t |= (1 << (lim - j - 1));
  74. if(i < t) swap(a[i], a[t]);
  75. }
  76. for(int l = 2; l <= len; l <<= 1)
  77. {
  78. int q = l >> 1;
  79. for(Comp* p = a; p != a + len; p += l)
  80. for(int i = 0; i < q; ++i)
  81. {
  82. Comp t = omg[len / l * i] * p[i + q];
  83. p[i + q] = p[i] - t, p[i] = p[i] + t;
  84. }
  85. }
  86. }
  87. char t[maxn << 1];
  88. int p[maxn << 1], m;
  89. void manacher()
  90. {
  91. t[0] = '@';
  92. for(int i = 0; i < n; ++i) t[i << 1 | 1] = '#', t[(i << 1) + 2] = s[i];
  93. m = (n << 1) + 2;
  94. t[m - 1] = '#'; t[m] = '$';
  95. int mx = 0, id;
  96. for(int i = 1; i < m; ++i)
  97. {
  98. if(mx > i) p[i] = min(p[(id << 1) - i], mx - i);
  99. else p[i] = 1;
  100. while(t[i - p[i]] == t[i + p[i]]) p[i]++;
  101. if(i + p[i] > mx) mx = p[i] + i, id = i;
  102. }
  103. }
  104. ll quickpow(ll a, ll b)
  105. {
  106. ll ret = 1;
  107. for(; b; b >>= 1, a = a * a % mod)
  108. if(b & 1) ret = ret * a % mod;
  109. return ret;
  110. }
  111. ll Ans = 0;
  112. int ans[maxn];
  113. int main()
  114. {
  115. scanf("%s", s);
  116. n = strlen(s);
  117. while(len < (n << 1)) len <<= 1;
  118. for(int i = 0 ; i < n; ++i) a[i] = (Comp){s[i] == 'a', 0}, b[i] = (Comp){s[i] == 'b', 0};
  119. init();
  120. fft(a, omg); fft(b, omg);
  121. for(int i = 0; i < len; ++i) a[i] = a[i] * a[i] + b[i] * b[i];
  122. fft(a, inv);
  123. for(int i = 0; i < len; ++i) ans[i] = ((a[i].x / len + 0.5) + 1) / 2;
  124. for(int i = 0; i < len; ++i) Ans = (Ans + quickpow(2, ans[i]) - 1) % mod;
  125. manacher();
  126. for(int i = 1; i < m; ++i) Ans = (Ans - (p[i] >> 1) + mod) % mod;
  127. write(Ans), enter;
  128. return 0;
  129. }

luogu P4199 万径人踪灭的更多相关文章

  1. 【洛谷】P4199 万径人踪灭

    题解 每种字符跑一遍FFT,得到\(i + j = k\)时匹配的个数(要÷2,对于相同位置的最后再加上 然后算出\(2^{cnt[k]}\)的和,最后再减去用mancher匹配出的连续回文子串的个数 ...

  2. 洛咕 P4199 万径人踪灭

    给了两条限制,但是第二条想想是没用的,直接manacher就可以减掉多余的部分了,所以要求满足第一条的方案 也不难,可以想到枚举每个中心点,计算两边有多少对距离中心相等的位置值也相等,假设有\(t\) ...

  3. P4199 万径人踪灭 FFT + manacher

    \(\color{#0066ff}{ 题目描述 }\) \(\color{#0066ff}{输入格式}\) 一行,一个只包含a,b两种字符的字符串 \(\color{#0066ff}{输出格式}\) ...

  4. 洛谷P4199 万径人踪灭(manacher+FFT)

    传送门 题目所求为所有的不连续回文子序列个数,可以转化为回文子序列数-回文子串数 回文子串manacher跑一跑就行了,考虑怎么求回文子序列数 我们考虑,如果$S_i$是回文子序列的对称中心,那么只要 ...

  5. 2019.2-2019.3 TO-DO LIST

    DP P2723 丑数 Humble Numbers(完成时间:2019.3.1) P2725 邮票 Stamps(完成时间:2019.3.1) P1021 邮票面值设计(完成时间:2019.3.1) ...

  6. FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ

    众所周知,tzc 在 2019 年(12 月 31 日)就第一次开始接触多项式相关算法,可到 2021 年(1 月 1 日)才开始写这篇 blog. 感觉自己开了个大坑( 多项式 多项式乘法 好吧这个 ...

  7. Luogu 魔法学院杯-第二弹(萌新的第一法blog)

    虽然有点久远  还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题  沉迷游戏,伤感情 #include <queue> ...

  8. luogu p1268 树的重量——构造,真正考验编程能力

    题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...

  9. 【bzoj3160】【xsy1726】万径人踪灭

    [bzoj3160]万径人踪灭 题意 给定一个由'a'和'b'构成的字符串,求不连续回文子序列的个数. \(n\leq 100000\) 分析 还是蛮不错的. 这道题基本上是自己想到的. 除了没有利用 ...

随机推荐

  1. Java基础教程(20)--数字和字符串

    一.数字   在用到数字时,大多数情况下我们都会使用基本数据类型.例如: int i = 500; float gpa = 3.65f; byte mask = 0xff;   然而,有时候我们既需要 ...

  2. JSP基础知识点

    JSP(Java Server Page)是主要有Sun公司倡导的一种动态网页技术,利用JSP可以构建跨平台的动态网站 应用,JSP在服务器端带JSP容器的Web服务器中运行.JSP以Java语言为基 ...

  3. Mac Supervisor 管理进程

    无论是在日常工作中还是平时玩代码中,我总是离不开 Supervisor,其实很久之前我就写过一篇文章:supervisord 部署 Flask,在里面,我仔细讲解了如何在 Linux 环境下安装并且配 ...

  4. CassiniDev源码学习 - 可替代IIS的单机Web Form解决方案

    最近一个项目是将web版的程序,改为单机版.话说这个web版号称当年十几个人用了至少3个月的时间开发,后来三年还不断有修改,而现在要在1个月内由一个人完成,这简直是不可能完成的任务!直觉告诉我,重写肯 ...

  5. wamp 安装monggo扩展

    1.下载对应的monggo扩展 http://pecl.php.net/package/mongo 2. 找对应的版本 放在D:\program\wamp\bin\php\php5.5.12\ext ...

  6. Code Signal_练习题_Array Replace

    Given an array of integers, replace all the occurrences of elemToReplace with substitutionElem. Exam ...

  7. javascript之原型

    写作背景 最近在抓基础,毕竟没有好地基盖楼容易塌啊...再回首javascript,原型可以说是该语言较为核心的设计之一,我们有必要了解下其设计理念 (#^.^#) 基本概念 MyObject.pro ...

  8. 【node】node的核心模块---http模块,http的服务器和客户端

    nodejs事件机制 ##### http服务器和客户端 node.js标准库提供了http模块,其中封装了一个高效的http服务器和一个简易的http客户端 HTTP服务器 1. http.crea ...

  9. 牛顿迭代法(Newton's Method)

    牛顿迭代法(Newton's Method) 简介 牛顿迭代法(简称牛顿法)由英国著名的数学家牛顿爵士最早提出.牛顿法的作用是使用迭代的方法来求解函数方程的根.简单地说,牛顿法就是不断求取切线的过程. ...

  10. 矩阵分解---QR正交分解,LU分解

    相关概念: 正交矩阵:若一个方阵其行与列皆为正交的单位向量,则该矩阵为正交矩阵,且该矩阵的转置和其逆相等.两个向量正交的意思是两个向量的内积为 0 正定矩阵:如果对于所有的非零实系数向量x ,都有 x ...