Description

Input & Output & Sample Input & Sample Output

HINT

题解:

题意即求不连续但间隔长度对称的回文串个数。

若si=sj,则这对字符可以作为以(i+j)/2为中心的回文串的一部分

用F[i]来表示可以做为以i/2为中心的回文串的一部分的字符对数,则以i/2为中心的回文串数为2^F[i]

则这就成了多项式乘法:先做一次a的,把字符为a的位置值赋为1,其余为0,进行一次FFT;同理做一次b的。

因为完全连续是不可以的,所以用Manacher求出这样的回文串的个数并减去。

代码:

(BZOJ上PASCAL跑得不够快,再加上这题时限只有10s,并没有AC,不知道那些用PASCAL通过的人是怎么卡常数的)

 uses math;
const
mo=;
type
xs=record
x,y:double;
end;
arr=array[..]of xs;
var
e,t:arr;
a:array[..]of arr;
n,m,i,ll,ans:longint;
ch:array[-..]of char;
b:array[-..]of longint;
z,ksm:array[..]of longint;
s:ansistring;
operator -(a,b:xs)c:xs;
begin c.x:=a.x-b.x; c.y:=a.y-b.y; end;
operator +(a,b:xs)c:xs;
begin c.x:=a.x+b.x; c.y:=a.y+b.y; end;
operator *(a,b:xs)c:xs;
begin c.x:=a.x*b.x-a.y*b.y; c.y:=a.x*b.y+a.y*b.x; end;
procedure manacher;
var k,l,i:longint;
begin
k:=-; l:=-; b[-]:=;
for i:= to m*- do
begin
if l>=i then
b[i]:=min(b[*k-i],l-i+)else b[i]:=;
while true do
begin
if ch[i+b[i]]=ch[i-b[i]] then inc(b[i])
else break;
end;
ans:=(ans+mo-(b[i]shr ))mod mo;
if i+b[i]->l then begin l:=i+b[i]-; k:=i; end;
end;
end;
procedure fft(xx:longint);
var i,j,q,k,l,c:longint;
t:xs;
begin
for i:= to n- do a[xx+,z[i]]:=a[xx,i];
xx:=xx+;
k:=n; l:=;
for i:=ll downto do
begin
k:=k shr ;
for j:= to k- do
begin
c:=j**l;
for q:= to l- do
begin
t:=e[q*k]*a[xx,c+l];
a[xx,c+l]:=a[xx,c]-t;
a[xx,c]:=a[xx,c]+t;
inc(c);
end;
end;
l:=l*;
end;
end;
begin
readln(s); m:=length(s);
ch[-]:='+';
for i:= to m- do ch[i*]:=s[i+];
ch[m*+]:='-';
manacher;
for i:= to m- do if ch[i*]='a' then a[,i].x:=;
for i:= to m- do if ch[i*]='b' then a[,i].x:=;
n:=;
while n<m* do begin n:=n*; inc(ll); end;
for i:= to n- do z[i]:=(z[i shr ]shr )or((i and )shl(ll-));
ksm[]:=; for i:= to do ksm[i]:=(ksm[i-]*)mod mo;
for i:= to n- do e[i].x:=cos(pi**i/n);
for i:= to n- do e[i].y:=sin(pi**i/n);
fft(); fft();
for i:= to n- do a[,i]:=a[,i]*a[,i]+a[,i]*a[,i];
for i:= to n- do e[i].y:=-e[i].y;
fft();
for i:= to m- do a[,i*].x:=a[,i*].x+n;
for i:= to n- do ans:=(ans+ksm[round(a[,i].x//n)]-)mod mo;
writeln(ans);
end.

PASCAL

 #include<bits/stdc++.h>
using namespace std;
int mo=;
typedef pair<double,double> pa;
pa operator + (pa a,pa b)
{ pa c; c.first=a.first+b.first; c.second=a.second+b.second; return c; }
pa operator - (pa a,pa b)
{ pa c; c.first=a.first-b.first; c.second=a.second-b.second; return c; }
pa operator * (pa a,pa b)
{ pa c; c.first=a.first*b.first-a.second*b.second; c.second=a.first*b.second+a.second*b.first; return c; }
pa a[][],e[];
char s[],s2[];
int n,ans,nn,m,ksm[],z[];
void manacher()
{
int l=,k=; z[]=;
for(int i=;i<=nn;i++)
{
if(l>=i)z[i]=min(z[*k-i],l-i);else z[i]=;
while(s2[i+z[i]+]==s2[i-z[i]-])z[i]++;
ans=(ans-(z[i]+)/)%mo; if(i+z[i]>l){ k=i; l=i+z[i]; }
}
}
void fft(int x)
{
for(int i=;i<m;i++)a[x+][z[i]]=a[x][i]; x++;
for(int k=m/,i=;i<m;i*=,k/=) for(int j=;j<m;j+=*i) for(int l=;l<i;l++)
{ pa t=e[k*l]*a[x][j+l+i]; a[x][j+l+i]=a[x][j+l]-t; a[x][j+l]=a[x][j+l]+t; }
}
int main()
{
scanf("%s",s+); n=strlen(s+); nn=; s2[]='!'; s2[]='*';
for(int i=;i<=n;i++){ nn++; s2[nn]=s[i]; nn++; s2[nn]='*'; } s2[nn+]='?';
manacher();
ksm[]=; for(int i=;i<=;i++)ksm[i]=ksm[i-]*%mo;
m=; while(m<*n)m=m*;
for(int i=;i<m;i++)z[i]=(z[i>>]>>)+(i&)*m/;
e[].first=; e[].first=cos(*acos(-)/m); e[].second=sin(*acos(-)/m);
for(int i=;i<m;i++)e[i]=e[i-]*e[];
for(int i=;i<=n;i++)if(s[i]=='a')a[][i-].first=; fft();
for(int i=;i<=n;i++)if(s[i]=='b')a[][i-].first=; fft();
for(int i=;i<m;i++)a[][i]=a[][i]*a[][i]+a[][i]*a[][i];
for(int i=;i<m;i++)e[i].second=-e[i].second;
fft();
for(int i=;i<m;i++)ans=(ans+ksm[((int)round(a[][i].first/m)+)/]-)%mo;
ans=(ans+mo)%mo;
printf("%d\n",ans);
}

C++

BZOJ3160万径人踪灭的更多相关文章

  1. [bzoj3160]万径人踪灭_FFT_Manacher

    万径人踪灭 bzoj-3160 题目大意:给定一个ab串.求所有的子序列满足:位置和字符都关于某条对称轴对称而且不连续. 注释:$1\le n\le 10^5$. 想法: 看了大爷的题解,OrzOrz ...

  2. BZOJ3160 万径人踪灭 字符串 多项式 Manachar FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8810140.html 题目传送门 - BZOJ3160 题意 给你一个只含$a,b$的字符串,让你选择一个子序列 ...

  3. BZOJ3160 万径人踪灭(FFT+manacher)

    容易想到先统计回文串数量,这样就去掉了不连续的限制,变为统计回文序列数量. 显然以某个位置为对称轴的回文序列数量就是2其两边(包括自身)对称相等的位置数量-1.对称有啥性质?位置和相等.这不就是卷积嘛 ...

  4. BZOJ3160: 万径人踪灭

    设a[i]=bool(s[i]=='a'),b[i]=bool(s[i]=='b'),考虑a和a.b和b的卷积,由于卷积是对称的,就可以统计出不连续回文子串个数了.可能说得比较简略.再用manache ...

  5. bzoj千题计划302:bzoj3160: 万径人踪灭

    https://www.lydsy.com/JudgeOnline/problem.php?id=3160 不连续的回文串数量=所有的回文序列数量-连续的回文子串 连续的回文子串: manacher ...

  6. BZOJ3160:万径人踪灭(FFT,Manacher)

    Solution $ans=$回文子序列$-$回文子串的数目. 后者可以用$manacher$直接求. 前者设$f[i]$表示以$i$为中心的对称的字母对数. 那么回文子序列的数量也就是$\sum_{ ...

  7. BZOJ3160 万径人踪灭 【fft + manacher】

    题解 此题略神QAQ orz po神牛 由题我们知道我们要求出: 回文子序列数 - 连续回文子串数 我们记为ans1和ans2 ans2可以用马拉车轻松解出,这里就不赘述了 问题是ans1 我们设\( ...

  8. BZOJ3160: 万径人踪灭(FFT,回文自动机)

    BZOJ传送门: 解题思路: FFT在处理卷积时可以将自己与自己卷,在某一种字母上标1其他标0,做字符集次就好了. (回文就是直接对称可以联系偶函数定义理解,根据这个性质就可以将字符串反向实现字符串匹 ...

  9. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

随机推荐

  1. ERROR 1010 (HY000): Error dropping database (can't rmdir './test/', errno: 17)

    在删除数据库的时候报标题所示错误 mysql> drop database test; ERROR (HY000): Error dropping database (can't rmdir ' ...

  2. AFNetworking 3.0 源码解读(二)之 AFSecurityPolicy

    在我们平时的开发中,对网络连接安全方面所做的努力,应该占据很重要的位置. 在解释AFSecurityPolicy之前,我们先把基础的http/https 知识简单的普及一下.获取这方面的信息可通过这本 ...

  3. Vertica节点宕机处理一例

    Vertica节点宕机处理一例: 查询数据库版本和各节点状态 常规方式启动宕机节点失败 进一步查看宕机节点的详细日志 定位问题并解决 1. 查询数据库版本和各节点状态 dbadmin=> sel ...

  4. 1元搭建自己的云服务器&解析域名

    最近在学做微信开发,没有自己的域名和服务器就不得不寄人篱下,索性自己就到云主机上搭建了个服务器,但是水平有限弄了一个下午~~有自己的域名和服务器的好处相信不用我多说了.比如日后可以有自己域名的个性博客 ...

  5. Entity Framework 教程——EF体系结构

    EF体系结构 下图是一张EF体系结构的全景图,让我们单独了解各个组件的用处. EDM (Entity Data Model): EDM由3个主要部分组成,概念模块(Conceptual Model), ...

  6. redis安装记录

    下载redishttps://redis.io/    下载 3.2.6版本 ,上传到服务器 . 解压tar -zxvf redis-3.2.6 .tar.gz 修改配置文件(修改redis.conf ...

  7. 谈谈对Spring IOC的理解(转)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  8. php设计模式总结-工厂模式

    使用工厂模式的目的或目标? 工厂模式的最大优点在于创建对象上面,就是把创建对象的过程封装起来,这样随时可以产生一个新的对象.减少代码进行复制粘帖,耦合关系重,牵一发动其他部分代码. 通俗的说,以前创建 ...

  9. Js 实现登录验证码

    Js代码: /** * 验证码 */function yzm(){ var codeChars = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a','b','c ...

  10. jquery 通过submit()方法 提交表单示例

    jquery 通过submit()方法 提交表单示例: 本示例:以用户注册作为例子.使用jquery中的submit()方法实现表单提交. 注:本示例仅提供了对表单的验证,本例只用选用了三个字段作为测 ...