P4199 万径人踪灭 [Manacher + FFT]
万径人踪灭万径人踪灭万径人踪灭
给出一个由 01 组成的字符串,问该字符串有多少不同的子序列满足:
- 子序列是一个回文序列
- 子序列不连续,即这个回文串不可以是原字符串上连续的子串
回文序列不仅要求值回文, 且要求位置回文.
正解部分\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∑AaAb
于是 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]相关推荐
- 【BZOJ3160】万径人踪灭 Manacher+FFT
[BZOJ3160]万径人踪灭 Description Input Output Sample Input Sample Output HINT 题解:自己想出来1A,先撒花~(其实FFT部分挺裸的) ...
- 洛谷P4199 万径人踪灭(manacher+FFT)
传送门 题目所求为所有的不连续回文子序列个数,可以转化为回文子序列数-回文子串数 回文子串manacher跑一跑就行了,考虑怎么求回文子序列数 我们考虑,如果$S_i$是回文子序列的对称中心,那么只要 ...
- 【BZOJ3160】 万径人踪灭(FFT,manacher)
前言 多项式真的很难♂啊qwq Solution 考虑求的是一个有间隔的回文串,相当于是: 总的答案-没有间隔的答案 考虑总的答案怎么计算?FFT卷一下就好了. 对于每一位字符,有两种取值,然后随便卷 ...
- 【BZOJ 3160】 3160: 万径人踪灭 (FFT)
3160: 万径人踪灭 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 1440 Solved: 799 Description Input Out ...
- 浅谈 FFT (终于懂一点了~~)
FFT(离散傅氏变换的快速算法) FFT(Fast Fourier Transformation)是离散傅氏变换(DFT)的快速算法.即为快速傅氏变换.它是根据离散傅氏变换的奇.偶.虚.实等特性,对离 ...
- 【bzoj3160】万径人踪灭
题意:给一个只含a.b的字符串,求所有的回文不连续子序列. manacher+FFT. 先求出所有回文序列,再减去连续子序列(即回文串). 将a.b分开考虑,对于一个对称轴,以其为回文中心的回文序列的 ...
- 2018十二月刷题列表
Preface \(2018\)年的尾巴,不禁感慨自己这一年的蜕变只能用蜕变来形容了. 而且老叶说我们今年没的参加清北冬令营可以参加CCF在广州二中举办的冬令营,只要联赛\(390+\)就应该可以报. ...
- 2019.2-2019.3 TO-DO LIST
DP P2723 丑数 Humble Numbers(完成时间:2019.3.1) P2725 邮票 Stamps(完成时间:2019.3.1) P1021 邮票面值设计(完成时间:2019.3.1) ...
- BZOJ 3160 FFT+Manacher
思路: 这道题思路好奇怪--. 我们先要知道关于x (x可以是间隙) 对称的有几对字母 显然暴力是n^2的 那怎么办呢 先把所有'a'看成1 'b'看成0 意外的发现 这不就是卷积嘛 再倒过来搞一搞 ...
- FFT与多项式、生成函数题目泛做
题目1 COGS 很强的乘法问题 高精度乘法用FFT加速 1 #include <cstdlib> 2 #include <iostream> 3 #include <a ...
最新文章
- CRMEB删除公众号首页logo动画
- LOJ dfs序1234
- r软件 image画出来的图是颠倒的_如何用Python抠图?试试scikitimage
- linux ip addr peer,CentOS 7 设置网络IP地址
- Mysql跨表更新 多表update sql语句总结
- servlet和springMVC框架
- 免费复制百度文库的方法
- Windows下telnet工具使用
- 更换yum源-阿里yum源
- Html post易语言服务器,POST其实很简单 15 易语言模块之精易模块
- Mac OS 源码 截屏工具
- 【收集】网络上各路大侠放出的面试题、求职技巧
- 计算机组成原理运算器设计实验之8位可控加减法电路设计
- 单片机考试不挂科就等于学好单片机了吗,别太天真了
- 360Tray.exe是什么进程?360Tray.exe程序及常见问题介绍
- 苹果电脑开机慢怎么办
- win10如何调整计算机时间同步,Win10系统如何设置时间同步间隔?修改时间同步频率的方法...
- 我谈“孙宇晨拍天价午餐”
- java 属性签名_java – 使用BouncyCastle将签名/身份验证的属性添加到CMS签名
- 电脑声道,如何查看电脑声卡是几声道的?
热门文章
- sqrt函数用法c语言 linux,C语言中sqrt函数如何使用
- 日期格式化在高并发场景下的解决方案
- VapourSynth压制教程 【Waifu2x N卡 放大教程】
- 你必须会的微服务之Hystrix熔断器
- 设计的银行账户管理系统,增加一个VIP账户的管理
- python开发面试自我介绍_面试中怎样做一个精彩的自我介绍
- 微信怎样授权群相册服务器,怎么创建微信群相册?微信群相册设置与创建全攻略(图文)...
- 跑步为什么不能过量(对身体的危害)
- elasticsearch 出现all shards failed异常?
- 《BJBR虚拟仿真解决方案(描述精选)》(Yanlz+SteamVR+5G+AI+VR+AR+MR+HR+BR+CR+DR+ER+FR+GR+人工智能+人机交互+立钻哥哥+==)