题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160

似乎理解加深了。

用卷积算相同的位置;先把 a 赋成1、 b 赋成0,卷积一遍;再把 a 赋成0、 b 赋成1,卷积一遍;两个加起来就有了每个位置的值,它表示以该位置/2(/2的位置可以是裂缝)为对称轴的回文位置个数。

然后用马拉车把连续区间的情况去掉。

注意一下单个元素也要算上,因为有那种奇数的;马拉车里别忘了把单个元素减去。

因为FFT的两个数组是一样的,所以FFT一次,然后自己乘自己就行了。

虽然调了很久但其实也没什么要注意的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define db double
using namespace std;
const int N=1e5+,M=N<<,mod=1e9+;
const db pi=acos(-);
int n,r[M],len,ans,bin[N];
char ch[N],tc[N<<];
struct cpl{db x,y;}a[M],b[M],I;
cpl operator+ (cpl a,cpl b){return (cpl){a.x+b.x,a.y+b.y};}
cpl operator- (cpl a,cpl b){return (cpl){a.x-b.x,a.y-b.y};}
cpl operator* (cpl a,cpl b){return (cpl){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};}
void upd(int &x){x>=mod?x-=mod:;x<?x+=mod:;}
void fft(cpl *a,bool fx)
{
for(int i=;i<len;i++)
if(i<r[i])swap(a[i],a[r[i]]);
for(int R=;R<=len;R<<=)//<<=1
{
int m=R>>;
cpl Wn=(cpl){ cos(pi/m),fx?-sin(pi/m):sin(pi/m) };
for(int i=;i<len;i+=R)
{
cpl w=I;
for(int j=;j<m;j++,w=w*Wn)//w=w*Wn
{
cpl tmp=w*a[i+m+j];
a[i+m+j]=a[i+j]-tmp;
a[i+j]=a[i+j]+tmp;
}
}
}
}
void manachar()
{
int m=(n<<)-;
for(int i=,j=;j<n;i+=,j++)
tc[i]=ch[j],tc[i+]=',';
int id=;
r[]=;ans--;
for(int i=;i<m;i++)
{
r[i]=;
if(id+r[id]>i)
{
r[i]=min(id+r[id]-i,r[(id<<)-i]);
}
if(id+r[id]<=i+r[i])
{
for(;i+r[i]<m&&i-r[i]>=&&tc[i+r[i]]==tc[i-r[i]];r[i]++);
r[i]--; id=i;
}
int tmp=(r[i]+(tc[i]==','))>>;//don't change r[i]!!!!!!
ans-=tmp+(tc[i]!=','); upd(ans);
}
}
int main()
{
I.x=;
scanf("%s",ch);n=strlen(ch);
bin[]=;
for(int i=,m=n+>>;i<=m;i++)bin[i]=bin[i-]<<,upd(bin[i]);
len=;
for(;len<=n<<;len<<=);
for(int i=;i<len;i++) r[i]=(r[i>>]>>)+((i&)?len>>:);
for(int i=;i<n;i++)
if(ch[i]=='a')a[i].x=;
fft(a,);
for(int i=;i<len;i++)a[i]=a[i]*a[i];
fft(a,);
for(int i=;i<n;i++)
if(ch[i]=='b')b[i].x=;
fft(b,);
for(int i=;i<len;i++)b[i]=b[i]*b[i];
fft(b,);
for(int i=;i<len;i++)//len
{
a[i].x=(int(a[i].x/len+0.5)+)>>;
b[i].x=(int(b[i].x/len+0.5)+)>>;
a[i].x+=b[i].x;
ans+=bin[(int)a[i].x]-; upd(ans);
}
manachar();
printf("%d\n",ans);
return ;
}

bzoj 3160 万径人踪灭——FFT的更多相关文章

  1. BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher

    BZOJ 3160: 万径人踪灭 题目传送门 [题目大意] 给定一个长度为n的01串,求有多少个回文子序列? 回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称. 假如 ...

  2. BZOJ 3160: 万径人踪灭 [fft manacher]

    3160: 万径人踪灭 题意:求一个序列有多少不连续的回文子序列 一开始zz了直接用\(2^{r_i}-1\) 总-回文子串 后者用manacher处理 前者,考虑回文有两种对称形式(以元素/缝隙作为 ...

  3. bzoj 3160 万径人踪灭 FFT

    万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1936  Solved: 1076[Submit][Status][Discuss] De ...

  4. bzoj 3160 万径人踪灭 —— FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 求出关于一个位置有多少对对称字母,如果 i 位置有 f[i] 对,对答案的贡献是 2^ ...

  5. bzoj 3160: 万径人踪灭 manachar + FFT

    3160: 万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 133  Solved: 80[Submit][Status][Discuss] ...

  6. 【BZOJ】3160: 万径人踪灭 FFT+回文串

    [题意]给定只含'a'和'b'字符串S,求不全连续的回文子序列数.n<=10^5. [算法]FFT+回文串 [题解]不全连续的回文子序列数=回文子序列总数-回文子串数. 回文子串数可以用回文串算 ...

  7. bzoj 3160: 万径人踪灭【FFT+manacher】

    考虑正难则反,我们计算所有对称子序列个数,再减去连续的 这里减去连续的很简单,manacher即可 然后考虑总的,注意到关于一个中心对称的两点下标和相同(这样也能包含以空位为对称中心的方案),所以设f ...

  8. BZOJ 3160: 万径人踪灭

    Description 一个ab串,问有多少回文子序列,字母和位置都对称,并且不连续. Sol FFT+Manacher. 不连续只需要减去连续的就可以了,连续的可以直接Manacher算出来. 其他 ...

  9. BZOJ 3160 万径人踪灭 解题报告

    这个题感觉很神呀.将 FFT 和 Manacher 有机结合在了一起. 首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ ...

随机推荐

  1. [转]AOP那些学术概念—通知、增强处理连接点(JoinPoint)切面(Aspect)

    AOP那些学术概念—通知.增强处理连接点(JoinPoint)切面(Aspect) 1.我所知道的AOP 初看起来,上来就是一大堆的术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充 ...

  2. 【Head First Servlets and JSP】笔记3:Servlet的生命周期

    1.servlet的存在就是要为客户服务.servlet的任务就是得到一个用户的请求,再发回一些响应. 请求可能很复杂,也可能很简单,例如,“为我的购物车结账”,这个请求携带了一些重要的数据,你必须知 ...

  3. [APIO2013]机器人

    题目描述 VRI(Voltron 机器人学会)的工程师建造了 n 个机器人.任意两个兼容的机 器人站在同一个格子时可以合并为一个复合机器人. 我们把机器人用 1 至 n 编号(n ≤ 9).如果两个机 ...

  4. 以太坊钱包Geth使用命令

    一.启动以太坊钱包Geth 打开一个控制台,执行同步区块命令 #同步测试链geth --fast --cache=512 --rpc --rpcapi personal,db,eth,net,web3 ...

  5. SOA 面向服务架构 阅读笔记(六)

    20 SOA质量 服务质量是成功的关键因素 20.1 了解SOA带来的无法预料的挑战 不同部门开发 每个开发的组件整合在一起,形成复合应用程序 整合业务流程,考虑质量问题 衡量SOA的质量. 事物质量 ...

  6. 在.h和.cpp中包含头文件的区别

    1.在.h中包含头文件,是为了声明一系列这个头文件的变量等,可能会产生重复包含的问题: 2.在.cpp中包含头文件只是为了实现这个头文件或者使用其中的方法,不会有重复包含的问题,所以尽量在源文件中包含 ...

  7. C++中substr的用法

    C++中substr函数的用法 #include<string> #include<iostream> using namespace std; void main() { s ...

  8. Linux基本常用命令

    说到Linux,它就是基于POSIX和UNIX的多用户,多任务,支持多线程和多CPU的操作系统.它能运行主要的UNIX的工具软件,应用程序和网络协议.它支持32位和64位硬件.linux继承Unix以 ...

  9. matplotlib两种画散点图的方式

    对于matplotlib.pyplot( as plt ) 先输入主体数据部分: import numpy as np import matplotlib.pyplot as plt X_train ...

  10. dr03_

    1.温州配调-->全网-->厂站-->瓯海-->竹溪变 1.1.“10kVI段”,“60号间隔”,手车开关 --> 合上 2. 2.1. 2.2. TdrSvgDll.A ...