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. call,apply,bind的用法

    关于call,apply,bind这三个函数的用法,是学习javascript这门语言无法越过的知识点.下边我就来好好总结一下它们三者各自的用法,及常见的应用场景. 首先看call这个函数,可以理解成 ...

  2. JS 对象封装的常用方式

    JS是一门面向对象语言,其对象是用prototype属性来模拟的,下面,来看看如何封装JS对象. 常规封装 function Person (name,age,sex){ this.name = na ...

  3. 《你不知道的JavaScript》整理(三)——对象

    一.语法 两种形式定义:文字形式和构造形式. //文字形式 var myObj = { key: value }; //构造形式 var myObj = new Object(); myObj.key ...

  4. JQuery中的工具函数总结

    前提引入 前提当然也是要引入Jquery啦... <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js" typ ...

  5. 【Python五篇慢慢弹】数据结构看python

    数据结构看python 作者:白宁超 2016年10月9日14:04:47 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondoc ...

  6. 密码学应用(DES,AES, MD5, SHA1, RSA, Salt, Pkcs8)

    目录 一.数据加密标准 - Data Encryption Standard(DES) 二.高级加密标准 - Advanced Encryption Standard(AES) 三.消息摘要算法第五版 ...

  7. 从N个元素的集合中随机取m个元素的算法实现

    最近有一个需求,比较简单,就是如标题所说的,从N个元素中随机取m个元素,当然这m个元素是不能存在重复的.本以为这么简单的需求,应该有现成的工具类来实现,但是几次查找居然没找到(有知道的可以推荐下哈^_ ...

  8. 一位同事对 Rafy 框架的一些建议及我的回复

    下面是一位同事对当前的产品开发框架提出的一些建议,以及我的回复.我觉得一些问题提得有一定的代表性,在征得本人同意后,将本邮件发布在博客中. 同时,也非常希望对框架.产品有好的建议的小伙伴,都可以给我发 ...

  9. 深度解析C语言int与unsigned int

    就如同int a:一样,int 也能被其它的修饰符修饰.除void类型外,基本数据类型之前都可以加各种类型修饰符,类型修饰符有如下四种:1.signed----有符号,可修饰char.int.Int是 ...

  10. Socket初识

    基础概念 Socket,套接字,本质是网络编程接口.提供网络通信的能力,实现不同虚拟机或不同计算机之间的通信.面向客户/服务(C/S)模型,socket是应用层和传输层之间的中间软件抽象层: 顶上三层 ...