BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher
BZOJ 3160: 万径人踪灭
题目传送门
【题目大意】
给定一个长度为n的01串,求有多少个回文子序列?
回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称。
假如x是对称轴,若 i 和 j 是对称且di=dj,i,j可以视为可行的一组。可行组数记为f[x]。
\(f[x]=\sum_{i=1}^{x-1}[d[x-i]==d[x+i]]\)
以x为对称轴的答案是2^(f[x])-1。
可以观察发现将d[i]=1的A[i]标为1,A与A做一次卷积,即可得出d[i]=1的f[]。(因为\(p^{x-i}*p^{x+i}=p^x\))
对d[i]=1的做一次卷积,对d[i]=0的做一次卷积,加起来就是完整的f[]。
由于单个连续一段的回文串不算,做一次manacher,减掉就行了。(ps:感觉这是强行加上去的条件,增加码量……)
正解:FFT+快速幂+manacher
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b))
using namespace std;
typedef long long ll;
const ll mods=1000000007;
const int N=101000;
const double pi=acos(-1.0);
char st[N];
int n,d[N<<1],dn;
int nn,k,F[N<<1];
ll sum,tp[N<<2],power[N<<2];
struct Complex
{
double real,image;
Complex() {}
Complex(double _real,double _image)
{
real=_real; image=_image;
}
friend Complex operator + (Complex A,Complex B) { return Complex(A.real+B.real,A.image+B.image); }
friend Complex operator - (Complex A,Complex B) { return Complex(A.real-B.real,A.image-B.image); }
friend Complex operator * (Complex A,Complex B) { return Complex(A.real*B.real-A.image*B.image,A.image*B.real+A.real*B.image); }
} A[N<<2],B[N<<2];
int rev[N<<2];
void FFT(Complex *A,int n,int DFT)
{
for(int i=0;i<n;i++) if(i<rev[i]) swap(A[i],A[rev[i]]);
for(int s=1;(1<<s)<=n;s++)
{
int mi=(1<<s);
Complex wn=Complex(cos(2*pi/mi),DFT*sin(2*pi/mi));
for(int t=0;t<n;t+=mi)
{
Complex w=Complex(1,0);
for(int j=0;j<(mi>>1);j++)
{
Complex u=A[t+j],v=w*A[t+j+(mi>>1)];
A[t+j]=u+v; A[t+j+(mi>>1)]=u-v;
w=w*wn;
}
}
}
if(DFT==-1) for(int i=0;i<n;i++) A[i].real/=n,A[i].image/=n;
}
ll manacher()
{
F[1]=0; int p=1; ll re=0ll;
for(int i=2;i<=dn;i++)
{
F[i]=imax(0,imin(F[2*p-i],F[p]+p-i));
while(d[i+F[i]+1]==d[i-F[i]-1]) F[i]++;
if(F[i]+i>F[p]+p) p=i;
re=(re+((F[i]+1)>>1))%mods;
}
return re;
}
ll Pow(ll x,ll y)
{
ll s=1ll;
for(;y;y>>=1,x=x*x%mods) s=s*x%mods;
return s;
}
int main()
{
scanf("%s",st); n=strlen(st);
dn=1; d[1]=4;
for(int i=1;i<=n;i++)
{
d[++dn]=3;
d[++dn]=st[i-1]-'a';
} d[++dn]=3; d[++dn]=5;
sum=(mods-manacher())%mods;
int m=n<<1; k=0;
for(nn=1;nn<=m;nn<<=1) k++;
for(int i=0;i<nn;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
power[0]=1ll;
for(int i=1;i<=nn;i++) power[i]=(power[i-1]<<1)%mods;
for(int i=1;i<=n;i++) if(st[i-1]=='a') A[i].real=1;
FFT(A,nn,1); for(int i=0;i<=nn;i++) B[i]=A[i]*A[i];
memset(A,0,sizeof(A));
for(int i=1;i<=n;i++) if(st[i-1]=='b') A[i].real=1;
FFT(A,nn,1); for(int i=0;i<=nn;i++) B[i]=B[i]+A[i]*A[i]; FFT(B,nn,-1);
for(int i=1;i<nn;i++) tp[i]=ll(B[i].real+0.5);
//for(int i=1;i<nn;i++) printf("%lld\n",tp[i]);
for(int i=1;i<nn;i++) (sum+=power[(tp[i]+1)>>1]-1)%=mods;
printf("%lld\n",(sum%mods+mods)%mods);
return 0;
}
BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher的更多相关文章
- BZOJ 3160: 万径人踪灭 [fft manacher]
3160: 万径人踪灭 题意:求一个序列有多少不连续的回文子序列 一开始zz了直接用\(2^{r_i}-1\) 总-回文子串 后者用manacher处理 前者,考虑回文有两种对称形式(以元素/缝隙作为 ...
- bzoj 3160 万径人踪灭 FFT
万径人踪灭 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1936 Solved: 1076[Submit][Status][Discuss] De ...
- bzoj 3160 万径人踪灭——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 似乎理解加深了. 用卷积算相同的位置:先把 a 赋成1. b 赋成0,卷积一遍:再把 ...
- bzoj 3160 万径人踪灭 —— FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 求出关于一个位置有多少对对称字母,如果 i 位置有 f[i] 对,对答案的贡献是 2^ ...
- bzoj 3160: 万径人踪灭 manachar + FFT
3160: 万径人踪灭 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 133 Solved: 80[Submit][Status][Discuss] ...
- 【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)
4332: JSOI2012 分零食 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 119 Solved: 66 Description 这里是欢乐 ...
- 【codeforces 623E】dp+FFT+快速幂
题目大意:用$[1,2^k-1]$之间的证书构造一个长度为$n$的序列$a_i$,令$b_i=a_1\ or\ a_2\ or\ ...\ or a_i$,问使得b序列严格递增的方案数,答案对$10^ ...
- P3321 [SDOI2015]序列统计 FFT+快速幂+原根
\(\color{#0066ff}{ 题目描述 }\) 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S.小C用这 ...
- [bzoj 1409] Password 矩阵快速幂+欧拉函数
考试的时候想到了矩阵快速幂+快速幂,但是忘(bu)了(hui)欧拉定理. 然后gg了35分. 题目显而易见,让求一个数的幂,幂是斐波那契数列里的一项,考虑到斐波那契也很大,所以我们就需要欧拉定理了 p ...
随机推荐
- iOS数组越界
数组越界就是假如你的下标总数现在为32个,然后你在下一秒又执行了一个方法要从50个数据里进行赋值啊筛选之类的,而你此时数组里的值为32个,50的数据还没有请求到,往往会出现数组越界的崩溃信息,大概是这 ...
- shopping car 2.0
#!/usr/bin/env python# -*- coding: utf-8 -*-# @Time : 2018/5/13 0013 10:20# @Author : Anthony.Waa# @ ...
- [转]Java设计模式学习心得
http://tech.it168.com/focus/200902/java-design/index.html http://tech.it168.com/j/2007-05-17/2007051 ...
- Codeforces Round #454
Masha and Bears Tic-Tac-Toe Shockers Seating of Students Party Power Tower Reverses
- LeetCode 287. Find the Duplicate Number (python 判断环,时间复杂度O(n))
LeetCode 287. Find the Duplicate Number 暴力解法 时间 O(nlog(n)),空间O(n),按题目中Note"只用O(1)的空间",照理是过 ...
- 修改ElementUI源码
1.克隆ElementUI官方仓库代码到本地 https://github.com/ElemeFE/element 2.在cmd命令行安装依赖 1)找到代码文件夹 cd element 2)npm ...
- 读书笔记「Python编程:从入门到实践」_2.变量和简单数据类型
做了大半年RPA了,用的工具是Kapow. 工作没有那么忙,不想就这么荒废着,想学点什么.就Python吧. 为期三个月,希望能坚持下来. 2.1 变量的命名和使用 变量名只能包含字母.数字和下划线. ...
- C# treeView 控件
#region --基础 ////设置目录树 ////添加根节点 //treeView1.Nodes.Add("0000000"); ////添加子节点 ////treeView1 ...
- python入门基础知识
1.python环境的安装 python2 python3 安装后添加环境变量 2.编码 最早编码ASCII码,主要有英文,数字,字符.一字节(byte),八位(bit),代表一个字符 unicode ...
- CDR是什么?CorelDRAW矢量绘图
CorelDRAW是矢量绘图软件 CorelDRAW Graphics Suite是加拿大Corel公司的平面设计软件: CorelDRAW 非凡的设计能力广泛地应用于商标设计.标志制作.模型绘制.插 ...