【BZOJ3160】 万径人踪灭(FFT,manacher)
前言
多项式真的很难♂啊qwq
Solution
考虑求的是一个有间隔的回文串,相当于是:
总的答案-没有间隔的答案
考虑总的答案怎么计算?FFT卷一下就好了。
对于每一位字符,有两种取值,然后随便卷起来,卷起来就是当前这一位之前与它相同的字符个数(这一位不能是‘0’,也就是被排斥的那一位)
然后就可以轻松解决?
是的。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<queue>
#include<algorithm>
#include<complex>
#define ll long long
#define re register
using namespace std;
inline int gi(){
int f=1,sum=0;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const int maxn=2000010,Mod=1e9+7;
const double Pi=acos(-1.0);
char s[maxn];
int len,N,M,p[maxn],r[maxn];
ll f[maxn],tw[maxn],ans;
complex<double>a[maxn],b[maxn];
ll manacher(){
s[len+len+1]='#';s[0]=' ';
for(int i=len;i;i--){
s[i*2]=s[i];s[i*2-1]='#';
}
int mx=0,id=0;
for(int i=1;i<=len+len;i++){
p[i]=mx>i?min(p[id*2-i],mx-i):1;
while(s[p[i]+i]==s[i-p[i]])p[i]++;
if(i+p[i]>mx){
id=i;mx=i+p[i];
}
}
ll ret=0;
for(int i=1;i<=len+len;i++)
ret=(ret+p[i]/2)%Mod;
return ret;
}
void FFT(complex<double> *P,int opt)
{
for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
{
complex<double> W(cos(Pi/i),opt*sin(Pi/i));
for(int p=i<<1,j=0;j<N;j+=p)
{
complex<double> w(1,0);
for(int k=0;k<i;++k,w*=W)
{
complex<double> X=P[j+k],Y=P[i+j+k]*w;;
P[j+k]=X+Y;P[i+j+k]=X-Y;
}
}
}
}
void work(char cc)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=len;++i)a[i]=b[i]=s[i]==cc;
FFT(a,1);FFT(b,1);
for(int i=0;i<N;++i)a[i]*=b[i];
FFT(a,-1);
for(int i=1;i<N;++i)a[i].real()=a[i].real()/N+0.5;
for(int i=0;i<=M;++i)f[i]+=((int)(a[i].real())+1)/2;
}
int main(){
scanf("%s",s+1);len=strlen(s+1);
M=len+len;tw[0]=1;
for(int i=1;i<=M;i++)tw[i]=(tw[i-1]+tw[i-1])%Mod;
int l=0;
for(N=1;N<=M;N<<=1)l++;
for(int i=0;i<N;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
work('a');work('b');
for(int i=1;i<=M;i++)ans=(ans+tw[f[i]]-1)%Mod;
printf("%lld\n",(ans-manacher()+Mod)%Mod);
return 0;
}
【BZOJ3160】 万径人踪灭(FFT,manacher)的更多相关文章
- BZOJ3160:万径人踪灭(FFT,Manacher)
Solution $ans=$回文子序列$-$回文子串的数目. 后者可以用$manacher$直接求. 前者设$f[i]$表示以$i$为中心的对称的字母对数. 那么回文子序列的数量也就是$\sum_{ ...
- BZOJ 3160: 万径人踪灭 [fft manacher]
3160: 万径人踪灭 题意:求一个序列有多少不连续的回文子序列 一开始zz了直接用\(2^{r_i}-1\) 总-回文子串 后者用manacher处理 前者,考虑回文有两种对称形式(以元素/缝隙作为 ...
- P4199 万径人踪灭 FFT + manacher
\(\color{#0066ff}{ 题目描述 }\) \(\color{#0066ff}{输入格式}\) 一行,一个只包含a,b两种字符的字符串 \(\color{#0066ff}{输出格式}\) ...
- BZOJ3160 万径人踪灭(FFT+manacher)
容易想到先统计回文串数量,这样就去掉了不连续的限制,变为统计回文序列数量. 显然以某个位置为对称轴的回文序列数量就是2其两边(包括自身)对称相等的位置数量-1.对称有啥性质?位置和相等.这不就是卷积嘛 ...
- BZOJ3160 万径人踪灭 【fft + manacher】
题解 此题略神QAQ orz po神牛 由题我们知道我们要求出: 回文子序列数 - 连续回文子串数 我们记为ans1和ans2 ans2可以用马拉车轻松解出,这里就不赘述了 问题是ans1 我们设\( ...
- BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher
BZOJ 3160: 万径人踪灭 题目传送门 [题目大意] 给定一个长度为n的01串,求有多少个回文子序列? 回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称. 假如 ...
- BZOJ3160 万径人踪灭 字符串 多项式 Manachar FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8810140.html 题目传送门 - BZOJ3160 题意 给你一个只含$a,b$的字符串,让你选择一个子序列 ...
- Luogu4199 万径人踪灭 FFT、Manacher
传送门 先不考虑”不是连续的一段“这一个约束条件.可以知道:第$i$位与第$j$位相同,可以对第$\frac{i+j}{2}$位置上产生$1$的贡献(如果$i+j$为奇数表明它会对一条缝产生$1$的贡 ...
- 万径人踪灭(FFT+manacher)
传送门 这题--我觉得像我这样的菜鸡选手难以想出来-- 题目要求求出一些子序列,使得其关于某个位置是对称的,而且不能是连续一段,求这样的子序列的个数.这个直接求很困难,但是我们可以先求出所有关于某个位 ...
- bzoj 3160: 万径人踪灭【FFT+manacher】
考虑正难则反,我们计算所有对称子序列个数,再减去连续的 这里减去连续的很简单,manacher即可 然后考虑总的,注意到关于一个中心对称的两点下标和相同(这样也能包含以空位为对称中心的方案),所以设f ...
随机推荐
- keybd_event使用方法
Windows提供了一个模拟键盘API函数Keybd_event(),使用该函数可以相应的屏蔽键盘的动作.Keybd_event()函数能触发一个按键事件,也就是说会产生一个WM_KEYDOWN或WM ...
- spring学习 十三 注解AOP
spring 不会自动去寻找注解,必须告诉 spring 哪些包下的类中可能有注解,也就是要开启注解扫描,注解的包是spring-context.jar,所以在配置文件中还要引入context约束,也 ...
- kbmmw 中JSON 中使用SQL 查询
前面讲到了kbmmw 的JSON 对象操作,如何快速的查找JSON 中的值? 一种办法就是通过遍历的方法,其实在kbmmw 还有一种灵活的查询方式, 就是通过SQL 方式查询JSON 中的值.也就是说 ...
- Oracle服务器修改IP后
机房有两套网络,一套办公网,一套机房的内网,办公网可以通过vpn在其他地方访问,内网只能在公司办公室访问.团队有同事去外地办公,开发的时候需要通过客户端直连数据库,于是把数据库服务器的网线换到办公网的 ...
- 784. Letter Case Permutation
这个题的思想很重要,两种方法 第一种,回溯法 class Solution { public: int sz; vector<string> letterCasePermutation(s ...
- 第9章 符合Python风格的对象
#<流畅的Python>读书笔记 # 第9章 符合Python风格的对象 # 本章包含以下话题: # 支持用于生成对象其他表示形式的内置函数(如repr().bytes(),等等) # 使 ...
- ACM-ICPC 2018 徐州赛区网络预赛 G Trace(逆向,两颗线段树写法)
https://nanti.jisuanke.com/t/31459 思路 凡是后面的轨迹对前面的轨迹有影响的,可以尝试从后往前扫 区间修改需要push_down,单点更新所以不需要push_up(用 ...
- linux命令tee用法
功能说明:读取标准输入的数据,并将其内容输出成文件. 语 法:tee [-ai][--help][--version][文件…] 补充说明:tee指令会从标准输入设备读取数据,将其内容输出到标准输出设 ...
- C++IO cin
cin cin.get() 每次只读缓冲区一个字符,不能接收空格 cin.getline() 读缓冲区一行,能够接收空格 cin.ignore(2) 忽略缓冲器2个字节 int i = cin.pee ...
- maven打包某个分支的包
maven打某个分支的包命令: mvn clean install -Dmaven.test.skip=true -Pdevelop