万径人踪灭万径人踪灭万径人踪灭

给出一个由 01 组成的字符串,问该字符串有多少不同的子序列满足:

  1. 子序列是一个回文序列
  2. 子序列不连续,即这个回文串不可以是原字符串上连续的子串

回文序列不仅要求值回文, 且要求位置回文.


正解部分\color{red}{正解部分}正解部分

Ans=num位置对称的回文子序列−num回文子串Ans = num_{位置对称的回文子序列} - num_{回文子串}Ans=num位置对称的回文子序列​−num回文子串​

设前者为 num1num_1num1​, 后者为 num2num_2num2​, 其中 num2num_2num2​ 可以通过 manachermanachermanacher 得出, 没学过的可以看 这里 .

所以现在只需考虑 num1num_1num1​ 怎么计算 .

  • 以整数位置 iii 为对称轴, 设满足 Si−j=Si+jS_{i-j}=S_{i+j}Si−j​=Si+j​ 的字母对数为 kkk, 算上 Si=SiS_i = S_iSi​=Si​ 总共产生了 2k+1−12^{k+1}-12k+1−1 种回文子序列, 那个 −1-1−1 是减去 全部都不选 的情况 .
  • 以小数位置 iii 为对称轴, 设满足 Si−j=Si+jS_{i-j}=S_{i+j}Si−j​=Si+j​ 的字母对数为 kkk, 则总共产生了 2k−12^k-12k−1 种回文子序列 .

构造多项式 Ai=[Si==′a′]A_i = [S_i==\ 'a']Ai​=[Si​== ′a′], 则

A2i2=∑a+b=2iAaAbA_{2i}^2=\sum\limits_{a+b=2i} A_aA_bA2i2​=a+b=2i∑​Aa​Ab​

于是 A2i2A_{2i}^2A2i2​ 就表示以 iii 位置为对称轴, Si−j=Si+j=′a′S_{i-j}=S_{i+j}='a'Si−j​=Si+j​=′a′ 的对数

于是 ⌈A2i22⌉\lceil \frac{A_{2i}^2}{2} \rceil⌈2A2i2​​⌉ 就表示以 iii 位置为对称轴, Si−j=Si+j=′a′S_{i-j}=S_{i+j}='a'Si−j​=Si+j​=′a′ 的对数

同理设 Bi=[Si==′b′]B_i = [S_i ==\ 'b']Bi​=[Si​== ′b′], ⌈B2i22⌉\lceil \frac{B_{2i}^2}{2} \rceil⌈2B2i2​​⌉就表示以 iii 为对称轴, Si−j=Si+j=′b′S_{i-j}=S_{i+j}='b'Si−j​=Si+j​=′b′ 的对数 .


然后 Ai2+Bi2A_i^2 + B_i^2Ai2​+Bi2​ 就可以得到以 i/2i/2i/2 为对称轴, Si2−j=Si2+jS_{\frac{i}{2}-j}=S_{\frac{i}{2}+j}S2i​−j​=S2i​+j​ 的对数 .

纵使 i/2i/2i/2 为小数也成立, 所以可以完美覆盖上方情况 .


实现部分\color{red}{实现部分}实现部分

其中多项式乘法可以使用 FFTFFTFFT 实现, 没学过的可以看 这里 .

#include<bits/stdc++.h>
typedef long long ll;
#define reg registerconst int maxn = 200005;
const int mod = 1e9 + 7;
const double Pi = acos(-1);int N;
int FFT_Len;
int pw[maxn];
int rev[maxn<<2];
int hw[maxn<<1];char S[maxn<<1];
char t[maxn<<1];struct complex{double x, y;complex(double x=0, double y=0):x(x), y(y) {}
} A[maxn<<2], B[maxn<<2];complex operator + (complex a, complex b){ return complex(a.x+b.x, a.y+b.y); }
complex operator - (complex a, complex b){ return complex(a.x-b.x, a.y-b.y); }
complex operator * (complex a, complex b){ return complex(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x); }int Ksm(int a, ll b){int s = 1;while(b){if(b & 1) s = 1ll*s*a % mod;a = 1ll*a*a % mod; b >>= 1;}return s;
}int Manacher(){int res = 0;t[0] = '#';for(reg int i = 1; i <= N; i ++) t[i*2-1] = S[i], t[i*2] = '#';t[N*2+1] = '#';int Max_r = 0, mid = 0;for(reg int i = 1; i <= N<<1; i ++){if(i <= Max_r) hw[i] = std::min(hw[(mid<<1)-i], Max_r-i+1);while(i-hw[i] >= 0 && i+hw[i] <= (N<<1)+1 && t[i-hw[i]] == t[i+hw[i]]) hw[i] ++;if(i+hw[i]-1 > Max_r) Max_r = i+hw[i]-1, mid = i;res += hw[i]/2;  // !if(res >= mod) res -= mod;}return res;
}void FFT(complex *F, int opt){for(reg int i = 0; i < FFT_Len; i ++)if(i < rev[i]) std::swap(F[i], F[rev[i]]);for(reg int p = 2; p <= FFT_Len; p <<= 1){int half = p >> 1;complex t = complex(cos(Pi/half), opt*sin(Pi/half));for(reg int i = 0; i < FFT_Len; i += p){complex buf = complex(1, 0);for(reg int k = i; k < i+half; k ++){complex Tmp = buf * F[k + half];F[k + half] = F[k] - Tmp;F[k] = F[k] + Tmp;buf = buf * t;}}}
}int Calc(){int res = 0;for(reg int i = 1; i <= N; i ++) A[i].x = S[i]=='a', B[i].x = S[i]=='b';FFT_Len = 1; int bit_n = 0;while(FFT_Len <= (N<<1)) bit_n ++, FFT_Len <<= 1;for(reg int i = 0; i < FFT_Len; i ++) rev[i] = (rev[i>>1]>>1) | ((i&1) << bit_n-1);FFT(A, 1), FFT(B, 1);for(reg int i = 0; i < FFT_Len; i ++) A[i] = A[i]*A[i] + B[i]*B[i];FFT(A, -1);for(reg int i = 0; i < FFT_Len; i ++) A[i].x = (A[i].x + 0.5)/FFT_Len;pw[0] = 1;for(reg int i = 1; i <= N; i ++) pw[i] = 2ll*pw[i-1] % mod;for(reg int i = 1; i <= (N<<1)+1; i ++){ll t1 = (A[i].x + 1)/2;res += pw[t1] - 1;if(res >= mod) res -= mod;}return res;
}int main(){scanf("%s", S+1);N = strlen(S+1);int p = Manacher();printf("%d\n", (1ll*Calc()-p+mod)%mod);return 0;
}

P4199 万径人踪灭 [Manacher + FFT]相关推荐

  1. 【BZOJ3160】万径人踪灭 Manacher+FFT

    [BZOJ3160]万径人踪灭 Description Input Output Sample Input Sample Output HINT 题解:自己想出来1A,先撒花~(其实FFT部分挺裸的) ...

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

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

  3. 【BZOJ3160】 万径人踪灭(FFT,manacher)

    前言 多项式真的很难♂啊qwq Solution 考虑求的是一个有间隔的回文串,相当于是: 总的答案-没有间隔的答案 考虑总的答案怎么计算?FFT卷一下就好了. 对于每一位字符,有两种取值,然后随便卷 ...

  4. 【BZOJ 3160】 3160: 万径人踪灭 (FFT)

    3160: 万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 1440  Solved: 799 Description Input Out ...

  5. 浅谈 FFT (终于懂一点了~~)

    FFT(离散傅氏变换的快速算法) FFT(Fast Fourier Transformation)是离散傅氏变换(DFT)的快速算法.即为快速傅氏变换.它是根据离散傅氏变换的奇.偶.虚.实等特性,对离 ...

  6. 【bzoj3160】万径人踪灭

    题意:给一个只含a.b的字符串,求所有的回文不连续子序列. manacher+FFT. 先求出所有回文序列,再减去连续子序列(即回文串). 将a.b分开考虑,对于一个对称轴,以其为回文中心的回文序列的 ...

  7. 2018十二月刷题列表

    Preface \(2018\)年的尾巴,不禁感慨自己这一年的蜕变只能用蜕变来形容了. 而且老叶说我们今年没的参加清北冬令营可以参加CCF在广州二中举办的冬令营,只要联赛\(390+\)就应该可以报. ...

  8. 2019.2-2019.3 TO-DO LIST

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

  9. BZOJ 3160 FFT+Manacher

    思路: 这道题思路好奇怪--. 我们先要知道关于x (x可以是间隙) 对称的有几对字母 显然暴力是n^2的 那怎么办呢 先把所有'a'看成1 'b'看成0 意外的发现 这不就是卷积嘛 再倒过来搞一搞 ...

  10. FFT与多项式、生成函数题目泛做

    题目1 COGS 很强的乘法问题 高精度乘法用FFT加速 1 #include <cstdlib> 2 #include <iostream> 3 #include <a ...

最新文章

  1. CRMEB删除公众号首页logo动画
  2. LOJ dfs序1234
  3. r软件 image画出来的图是颠倒的_如何用Python抠图?试试scikitimage
  4. linux ip addr peer,CentOS 7 设置网络IP地址
  5. Mysql跨表更新 多表update sql语句总结
  6. servlet和springMVC框架
  7. 免费复制百度文库的方法
  8. Windows下telnet工具使用
  9. 更换yum源-阿里yum源
  10. Html post易语言服务器,POST其实很简单 15 易语言模块之精易模块
  11. Mac OS 源码 截屏工具
  12. 【收集】网络上各路大侠放出的面试题、求职技巧
  13. 计算机组成原理运算器设计实验之8位可控加减法电路设计
  14. 单片机考试不挂科就等于学好单片机了吗,别太天真了
  15. 360Tray.exe是什么进程?360Tray.exe程序及常见问题介绍
  16. 苹果电脑开机慢怎么办
  17. win10如何调整计算机时间同步,Win10系统如何设置时间同步间隔?修改时间同步频率的方法...
  18. 我谈“孙宇晨拍天价午餐”
  19. java 属性签名_java – 使用BouncyCastle将签名/身份验证的属性添加到CMS签名
  20. 电脑声道,如何查看电脑声卡是几声道的?

热门文章

  1. sqrt函数用法c语言 linux,C语言中sqrt函数如何使用
  2. 日期格式化在高并发场景下的解决方案
  3. VapourSynth压制教程 【Waifu2x N卡 放大教程】
  4. 你必须会的微服务之Hystrix熔断器
  5. 设计的银行账户管理系统,增加一个VIP账户的管理
  6. python开发面试自我介绍_面试中怎样做一个精彩的自我介绍
  7. 微信怎样授权群相册服务器,怎么创建微信群相册?微信群相册设置与创建全攻略(图文)...
  8. 跑步为什么不能过量(对身体的危害)
  9. elasticsearch 出现all shards failed异常?
  10. 《BJBR虚拟仿真解决方案(描述精选)》(Yanlz+SteamVR+5G+AI+VR+AR+MR+HR+BR+CR+DR+ER+FR+GR+人工智能+人机交互+立钻哥哥+==)