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的更多相关文章

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

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

  2. bzoj 3160 万径人踪灭 FFT

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

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 似乎理解加深了. 用卷积算相同的位置:先把 a 赋成1. b 赋成0,卷积一遍:再把 ...

  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 4332】 4332: JSOI2012 分零食 (FFT+快速幂)

    4332: JSOI2012 分零食 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 119  Solved: 66 Description 这里是欢乐 ...

  7. 【codeforces 623E】dp+FFT+快速幂

    题目大意:用$[1,2^k-1]$之间的证书构造一个长度为$n$的序列$a_i$,令$b_i=a_1\ or\ a_2\ or\ ...\ or a_i$,问使得b序列严格递增的方案数,答案对$10^ ...

  8. P3321 [SDOI2015]序列统计 FFT+快速幂+原根

    \(\color{#0066ff}{ 题目描述 }\) 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S.小C用这 ...

  9. [bzoj 1409] Password 矩阵快速幂+欧拉函数

    考试的时候想到了矩阵快速幂+快速幂,但是忘(bu)了(hui)欧拉定理. 然后gg了35分. 题目显而易见,让求一个数的幂,幂是斐波那契数列里的一项,考虑到斐波那契也很大,所以我们就需要欧拉定理了 p ...

随机推荐

  1. iOS数组越界

    数组越界就是假如你的下标总数现在为32个,然后你在下一秒又执行了一个方法要从50个数据里进行赋值啊筛选之类的,而你此时数组里的值为32个,50的数据还没有请求到,往往会出现数组越界的崩溃信息,大概是这 ...

  2. shopping car 2.0

    #!/usr/bin/env python# -*- coding: utf-8 -*-# @Time : 2018/5/13 0013 10:20# @Author : Anthony.Waa# @ ...

  3. [转]Java设计模式学习心得

    http://tech.it168.com/focus/200902/java-design/index.html http://tech.it168.com/j/2007-05-17/2007051 ...

  4. Codeforces Round #454

    Masha and Bears Tic-Tac-Toe Shockers Seating of Students Party Power Tower Reverses

  5. LeetCode 287. Find the Duplicate Number (python 判断环,时间复杂度O(n))

    LeetCode 287. Find the Duplicate Number 暴力解法 时间 O(nlog(n)),空间O(n),按题目中Note"只用O(1)的空间",照理是过 ...

  6. 修改ElementUI源码

    1.克隆ElementUI官方仓库代码到本地  https://github.com/ElemeFE/element 2.在cmd命令行安装依赖 1)找到代码文件夹 cd element 2)npm ...

  7. 读书笔记「Python编程:从入门到实践」_2.变量和简单数据类型

    做了大半年RPA了,用的工具是Kapow. 工作没有那么忙,不想就这么荒废着,想学点什么.就Python吧. 为期三个月,希望能坚持下来. 2.1 变量的命名和使用 变量名只能包含字母.数字和下划线. ...

  8. C# treeView 控件

    #region --基础 ////设置目录树 ////添加根节点 //treeView1.Nodes.Add("0000000"); ////添加子节点 ////treeView1 ...

  9. python入门基础知识

    1.python环境的安装 python2 python3 安装后添加环境变量 2.编码 最早编码ASCII码,主要有英文,数字,字符.一字节(byte),八位(bit),代表一个字符 unicode ...

  10. CDR是什么?CorelDRAW矢量绘图

    CorelDRAW是矢量绘图软件 CorelDRAW Graphics Suite是加拿大Corel公司的平面设计软件: CorelDRAW 非凡的设计能力广泛地应用于商标设计.标志制作.模型绘制.插 ...