考虑正难则反,我们计算所有对称子序列个数,再减去连续的

这里减去连续的很简单,manacher即可

然后考虑总的,注意到关于一个中心对称的两点下标和相同(这样也能包含以空位为对称中心的方案),所以设f[i]为下标和为i的对称中心一共有多少对相同字符,这样总答案就是\( \sum_{i=0}{2*n-2}2{f[i]}-1 \)(减掉的1是减掉空集)

然后考虑f怎么求,\( f[i]=((\sum_{j=0}^{i-1}s[j]s[i-j])+1)/2 \),除2是因为每一对都被算了两遍

暴力是不行的,但是这个(j,i-j)看着非常卷积,所以考虑怎么用FFT优化一下,把a字符和b字符分开算,以算a字符为例,做一个数组a[i]=(s[i]'a')?1:0,然后多项式是\( \sum_{j=0}^{i-1}a[j]*a[i-j]) \),这样就只算了对称且两点都是a的方案数,b同理

然后减掉manacher结果即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=500005,mod=1e9+7;
int n,f[N],bt,lm,re[N];
long long ans;
char c[N],s[N];
struct cd
{
double a,b;
cd(double A=0,double B=0)
{
a=A,b=B;
}
cd operator + (const cd &x) const
{
return cd(a+x.a,b+x.b);
}
cd operator - (const cd &x) const
{
return cd(a-x.a,b-x.b);
}
cd operator * (const cd &x) const
{
return cd(a*x.a-b*x.b,a*x.b+b*x.a);
}
}a[N],b[N];
void dft(cd a[],int f)
{
for(int i=0;i<lm;i++)
if(i<re[i])
swap(a[i],a[re[i]]);
for(int i=1;i<lm;i<<=1)
{
cd wi=cd(cos(M_PI/i),f*sin(M_PI/i));
for(int k=0;k<lm;k+=(i<<1))
{
cd w=cd(1,0),x,y;
for(int j=0;j<i;j++)
{
x=a[j+k],y=w*a[i+j+k];
a[j+k]=x+y,a[i+j+k]=x-y;
w=w*wi;
}
}
}
if(f==-1)
for(int i=0;i<lm;i++)
a[i].a/=lm;
}
long long ksm(long long a,long long b)
{
long long r=1;
while(b)
{
if(b&1)
r=r*a%mod;
a=a*a%mod;
b>>=1;
}
return r;
}
int main()
{
scanf("%s",c);
n=strlen(c);
for(bt=0;(1<<bt)<=2*n;bt++);
lm=(1<<bt);
for(int i=0;i<lm;i++)
re[i]=(re[i>>1]>>1)|((i&1)<<(bt-1));
for(int i=0;i<lm;i++)
a[i].a=(c[i]=='a')?1:0,a[i].b=0;
dft(a,1);
for(int i=0;i<lm;i++)
b[i]=a[i]*a[i];
for(int i=0;i<lm;i++)
a[i].a=(c[i]=='b')?1:0,a[i].b=0;
dft(a,1);
for(int i=0;i<lm;i++)
b[i]=b[i]+a[i]*a[i];
dft(b,-1);
for(int i=0;i<=2*(n-1);i++)
ans=(ans+ksm(2,((int)(b[i].a+0.5)+1)/2)-1)%mod;//cerr<<ans<<endl;
for(int i=0;i<n;i++)
s[(i+1)*2]=c[i],s[(i+1)*2+1]='#';
s[0]='$',s[1]='#',s[2*n+2]='&';
for(int i=1,mx=0,w;i<2*n+1;i++)
{
if(i<mx)
f[i]=min(f[2*w-i],mx-i);
else
f[i]=1;
for(;s[i-f[i]]==s[i+f[i]];f[i]++);
if(i+f[i]>mx)
mx=i+f[i],w=i;
ans=(ans-f[i]/2+mod)%mod;
}
printf("%lld\n",(ans%mod+mod)%mod);
return 0;
}

bzoj 3160: 万径人踪灭【FFT+manacher】的更多相关文章

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

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

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

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

  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 似乎理解加深了. 用卷积算相同的位置:先把 a 赋成1. b 赋成0,卷积一遍:再把 ...

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

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

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

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

  7. BZOJ 3160: 万径人踪灭

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

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

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

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

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

随机推荐

  1. CMS - tabBar

    Tips:如果网页图片(文字)看不清,请按CTRL+鼠标滚轮 1.建议使用阿里图库 或者 easyicon 2.建议使用81*81且低于40KB的图片(建议jpg) 3.如需查看脑图结构,请点击:ta ...

  2. vs2010 msvcr100.DLL 丢失!!! 用release 就可以了

  3. java学习方向及主要内容

    Java分成J2ME(移动应用开发),J2SE(桌面应用开发),J2EE(Web企业级应用),所以java并不是单机版的,只是面向对象语言.建议如果学习java体系的话可以这样去学习: *第一阶段:J ...

  4. Robots协议应用与写法研究

  5. java中创建对象的五种方法

    用最简单的描述来区分new关键字和newInstance()方法的区别:newInstance: 弱类型.低效率.只能调用无参构造.new: 强类型.相对高效.能调用任何public构造. newIn ...

  6. sql索引原理以及优化

    http://itindex.net/detail/52237-%E7%B4%A2%E5%BC%95-%E5%8E%9F%E7%90%86 http://itindex.net/detail/5171 ...

  7. Eos的Wasm智能合约的局限性

    官方只支持用C++写智能合约 用C++写智能合约门槛过高,会把许多开发者挡在门外,C++的复杂性也会让智能合约的设计变得困难. Wasm智能合约的效率并不是最优 由于C++最终也是编译成wasm字节码 ...

  8. Oracle:sequence问题研究

    一直以来,以为sequence是不间断地持续增长的:但今天发现sequence是会跳号,这种情况发生在RAC环境下.在单实例环境下,应该不存在的. sequence截图如下: 数据库表中发生了跳号: ...

  9. 【Java】DateUtil(1)

    import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...

  10. receive和process的过程

    (一) receive最终在fuse_kern_chan.c中的fuse_kern_chan_receive函数实现,使用系统调用读取 res = read(fuse_chan_fd(ch), buf ...