BZOJ3160万径人踪灭
Description
.jpg)
.jpg)
Input & Output & Sample Input & Sample Output
.jpg)
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万径人踪灭的更多相关文章
- [bzoj3160]万径人踪灭_FFT_Manacher
万径人踪灭 bzoj-3160 题目大意:给定一个ab串.求所有的子序列满足:位置和字符都关于某条对称轴对称而且不连续. 注释:$1\le n\le 10^5$. 想法: 看了大爷的题解,OrzOrz ...
- BZOJ3160 万径人踪灭 字符串 多项式 Manachar FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8810140.html 题目传送门 - BZOJ3160 题意 给你一个只含$a,b$的字符串,让你选择一个子序列 ...
- BZOJ3160 万径人踪灭(FFT+manacher)
容易想到先统计回文串数量,这样就去掉了不连续的限制,变为统计回文序列数量. 显然以某个位置为对称轴的回文序列数量就是2其两边(包括自身)对称相等的位置数量-1.对称有啥性质?位置和相等.这不就是卷积嘛 ...
- BZOJ3160: 万径人踪灭
设a[i]=bool(s[i]=='a'),b[i]=bool(s[i]=='b'),考虑a和a.b和b的卷积,由于卷积是对称的,就可以统计出不连续回文子串个数了.可能说得比较简略.再用manache ...
- bzoj千题计划302:bzoj3160: 万径人踪灭
https://www.lydsy.com/JudgeOnline/problem.php?id=3160 不连续的回文串数量=所有的回文序列数量-连续的回文子串 连续的回文子串: manacher ...
- BZOJ3160:万径人踪灭(FFT,Manacher)
Solution $ans=$回文子序列$-$回文子串的数目. 后者可以用$manacher$直接求. 前者设$f[i]$表示以$i$为中心的对称的字母对数. 那么回文子序列的数量也就是$\sum_{ ...
- BZOJ3160 万径人踪灭 【fft + manacher】
题解 此题略神QAQ orz po神牛 由题我们知道我们要求出: 回文子序列数 - 连续回文子串数 我们记为ans1和ans2 ans2可以用马拉车轻松解出,这里就不赘述了 问题是ans1 我们设\( ...
- BZOJ3160: 万径人踪灭(FFT,回文自动机)
BZOJ传送门: 解题思路: FFT在处理卷积时可以将自己与自己卷,在某一种字母上标1其他标0,做字符集次就好了. (回文就是直接对称可以联系偶函数定义理解,根据这个性质就可以将字符串反向实现字符串匹 ...
- 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】
原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...
随机推荐
- Oracle AWR报告提取方法
本文旨在用来指导项目人员自行提取Oracle数据库的AWR报告. 1.当前连接实例的AWR报告提取:@?/rdbms/admin/awrrpt 2.RAC的其他实例AWR报告提取:@?/rdbms/a ...
- .net请求URL过长,解决方案
<system.web> 节点下加上 <httpRuntime requestValidationMode="2.0" maxQueryStringLength= ...
- 从三栏自适应宽度布局到css布局的讨论
如何实现一个三栏自适应布局,左右各100px,中间随着浏览器宽度自适应? 第一个想到的是使用table布局,设置table的宽度为100%,三个td,第1个和第3个固定宽度为100px,那么中间那个就 ...
- 虚拟机安装CentOS6.4
1 概述 虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统,运行在主机上,完全独立,虚拟机里面的所有操作不会影响主机,即使虚拟 ...
- 让我们再为C#异步编程Async正名
本文版权归博客园和作者吴双本人共同所有.转载和爬虫必须在显要位置注明出处:http://www.cnblogs.com/tdws 半年前翻译了一系列很糟糕的异步编程文章,用异步的常用语来说:" ...
- C语言计算2个数的最小公倍数
#include<stdio.h>int main(){ int a,b,i=1,temp,lcm; scanf("%d %d",&a,&b); ...
- php调用web service接口(.net开发的接口)
实例代码1: try { $this->soapClientObj = new SoapClient(self::URL . '?wsdl', array('connection_timeout ...
- Live555流媒体服务器编译(Windows下)
最近在回顾之前做过的相关项目,其中包括live555流媒体服务器相关,今天先把live555开源框架在Windows下的编译方法记录一下. live555是一套使用使用开放的标准协议(RTP/RTCP ...
- spider RPC过滤器
spider支持在请求执行前或完成后进行特殊处理,比如安全性检查.敏感字段混淆等等.为此,spider提供了BeforeFilter和AfterFilter.其执行位置如下图所示: 流水线插件配置在s ...
- tomcat 504 gateway time-out
今天有个环境ajax调用一个请求的时候,出现一个504 gateway time-out响应,原以为是nginx找不到资源的问题,恰当我们的服务器上又配置了nginx,看了配置文件,没有指向tomca ...