bzoj 3160 万径人踪灭 —— FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160
求出关于一个位置有多少对对称字母,如果 i 位置有 f[i] 对,对答案的贡献是 2^f[i] - 1;
然后减去连续的,用 manachar 求出回文长度,每个位置作为边界都是一种不合法情况;
求对称,首先把字符串中间穿插字符 '$',于是字符串的长度变成2倍;
考虑一对字母 s[x],s[y],如果 s[x] = s[y],其对称中心是 (x+y)/2;
放在加入字符后的字符串中,对称中心就是 x+y;
所以可以看出卷积了:f[i] = ∑(0<=j<=i) (s[j]==s[i-j]),其中 i 视为新字符串中的位置,j 和 i-j 视为原字符串中的位置;
注意卷积和 manachar 算的个数都要包括自己成对,否则判断挺麻烦...
这里卷积的两个多项式其实是一样的,所以只要用 FFT 算出一个,然后自己乘起来即可;
做下一步的时候注意清空,别忘了清空 n~lim 部分的值;
处理 bin 的边界是 n 而非 n-1,因为最多可能有 n 对。
(学习了 manachar 的简洁写法)
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double db;
int const xn=(<<),mod=1e9+;
db const Pi=acos(-1.0);
int n,rev[xn],lim=,l,len[xn],bin[xn],c[xn];
char ch[xn];
struct com{db x,y;}a[xn],b[xn],aa[xn];
com operator + (com a,com b){return (com){a.x+b.x,a.y+b.y};}
com operator - (com a,com b){return (com){a.x-b.x,a.y-b.y};}
com operator * (com a,com b){return (com){a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y};}
int upt(int x){while(x>=mod)x-=mod; while(x<)x+=mod; return x;}
void fft(com *a,int tp)
{
for(int i=;i<lim;i++)
if(i<rev[i])swap(a[i],a[rev[i]]);
for(int mid=;mid<lim;mid<<=)
{
com wn=(com){cos(Pi/mid),tp*sin(Pi/mid)};
for(int j=,len=(mid<<);j<lim;j+=len)
{
com w=(com){,};
for(int k=;k<mid;k++,w=w*wn)
{
com x=a[j+k],y=w*a[j+mid+k];
a[j+k]=x+y; a[j+mid+k]=x-y;
}
}
}
}
void solve()
{
for(int i=;i<n;i++)a[i].x=(ch[i]=='a');
fft(a,);
for(int i=;i<lim;i++)b[i]=a[i]*a[i];
for(int i=;i<n;i++)a[i].x=(ch[i]=='b'),a[i].y=;//y=0
for(int i=n;i<lim;i++)a[i].x=,a[i].y=;//!!
fft(a,);
for(int i=;i<lim;i++)b[i]=b[i]+a[i]*a[i];
fft(b,-);
for(int i=;i<n+n;i++)c[i]=(c[i]+(int)(b[i].x/lim+0.5))%mod;
}
char s[xn];
int manachar()//+i self
{
int mx=,id=,ret=; s[]='$';
for(int i=;i<=n+n;i++)
if(i%==)s[i]='$';
else s[i]=ch[i>>];
for(int i=;i<=n+n;i++)
{
if(i<mx)len[i]=min(mx-i,len[id*-i]);
while(i-len[i]>=&&i+len[i]<=n+n&&s[i-len[i]]==s[i+len[i]])len[i]++;
if(i+len[i]>mx)mx=i+len[i],id=i;
ret=upt(ret+len[i]/);
}
return ret;
}
int main()
{
scanf("%s",ch); n=strlen(ch);
while(lim<=n+n)lim<<=,l++;//
for(int i=;i<lim;i++)
rev[i]=((rev[i>>]>>)|((i&)<<(l-)));
bin[]=;
for(int i=;i<=n;i++)bin[i]=upt(bin[i-]+bin[i-]);
solve();
int ans=;
for(int i=;i<n+n;i++)ans=upt(ans+bin[(c[i]+)>>]-);//+1 -1
printf("%d\n",upt(ans-manachar()));
return ;
}
bzoj 3160 万径人踪灭 —— FFT的更多相关文章
- BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher
BZOJ 3160: 万径人踪灭 题目传送门 [题目大意] 给定一个长度为n的01串,求有多少个回文子序列? 回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称. 假如 ...
- BZOJ 3160: 万径人踪灭 [fft manacher]
3160: 万径人踪灭 题意:求一个序列有多少不连续的回文子序列 一开始zz了直接用\(2^{r_i}-1\) 总-回文子串 后者用manacher处理 前者,考虑回文有两种对称形式(以元素/缝隙作为 ...
- bzoj 3160 万径人踪灭——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 似乎理解加深了. 用卷积算相同的位置:先把 a 赋成1. b 赋成0,卷积一遍:再把 ...
- bzoj 3160 万径人踪灭 FFT
万径人踪灭 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1936 Solved: 1076[Submit][Status][Discuss] De ...
- bzoj 3160: 万径人踪灭 manachar + FFT
3160: 万径人踪灭 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 133 Solved: 80[Submit][Status][Discuss] ...
- 【BZOJ】3160: 万径人踪灭 FFT+回文串
[题意]给定只含'a'和'b'字符串S,求不全连续的回文子序列数.n<=10^5. [算法]FFT+回文串 [题解]不全连续的回文子序列数=回文子序列总数-回文子串数. 回文子串数可以用回文串算 ...
- bzoj 3160: 万径人踪灭【FFT+manacher】
考虑正难则反,我们计算所有对称子序列个数,再减去连续的 这里减去连续的很简单,manacher即可 然后考虑总的,注意到关于一个中心对称的两点下标和相同(这样也能包含以空位为对称中心的方案),所以设f ...
- BZOJ 3160: 万径人踪灭
Description 一个ab串,问有多少回文子序列,字母和位置都对称,并且不连续. Sol FFT+Manacher. 不连续只需要减去连续的就可以了,连续的可以直接Manacher算出来. 其他 ...
- BZOJ 3160 万径人踪灭 解题报告
这个题感觉很神呀.将 FFT 和 Manacher 有机结合在了一起. 首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ ...
随机推荐
- Python3 与 C# 面向对象之~继承与多态 Python3 与 C# 面向对象之~封装 Python3 与 NetCore 基础语法对比(Function专栏) [C#]C#时间日期操作 [C#]C#中字符串的操作 [ASP.NET]NTKO插件使用常见问题 我对C#的认知。
Python3 与 C# 面向对象之-继承与多态 文章汇总:https://www.cnblogs.com/dotnetcrazy/p/9160514.html 目录: 2.继承 ¶ 2.1.单继 ...
- windows下通过VNC图形化訪问Ubuntu桌面环境
要在windows下图形化訪问Ubuntu或其他Linux系统桌面环境有非常多方法.我比較喜欢的是使用VNC服务,须要在Ubuntu下安装vncserver和在windows下安装client訪问工具 ...
- diff patch
http://rails-deployment.group.iteye.com/group/wiki/1318-diff-and-patch-10-minutes-guide 情景一:你正尝试从代码编 ...
- TIP2
mktemp :建立暂存/临时文件 more to see 'man mktemp' 语 法 mktemp[选择参数] 功 能 mktemp 命令:用于建立暂存文件,提供给shell脚本安全的使用临时 ...
- jvm基础(1)
1.整型数和浮点型数的表示 原码:第一位为符号位(0为正数,1为负数). 反码:符号位不动,源码取反. 正数补码:和原码相同. 负数补码:符号位不动,反码加1. 例如5的二进制表示可以是0000010 ...
- Openlayers中layer介绍
1.base layers & overlay layers base layer:最底层的layer,其它的图层是在他之上,最先增加的图层默认作为base layer. overlay la ...
- cookie、session及实现记住密码,自动登录
在登录帐号.密码框下,有三种帐号登录模式可供选择,用户可根据自己的具体情况选择其中一种适合自己的模式. 1.网吧模式:勾选网吧模式后,登录的帐号会在歪歪注销/退出的时候自动清除,不会留在登录框中,可以 ...
- 【百度之星初赛A】路径交 LCA+线段树
[百度之星初赛A]路径交 Problem Description 给定一棵n个点的树,以及m条路径,每次询问第L条到第R条路径的交集部分的长度(如果一条边同时出现在2条路径上,那么它属于路径的交集). ...
- 解决对象不支持“getElementsByClassName”属性或方法 ie兼容性
解决 IE 或者兼容模式不支持 document.getElementsByClassName() 的方法 自已实现document.getElementsByClassName(): 网页错 ...
- 九度OJ 1096:日期差值 (日期计算)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8138 解决:2752 题目描述: 有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天 输入: 有多组数据, ...