【BZOJ3160】万径人踪灭 Manacher+FFT
【BZOJ3160】万径人踪灭
Description
.jpg)
.jpg)
Input
.jpg)
Output
Sample Input
Sample Output
HINT
题解:自己想出来1A,先撒花~(其实FFT部分挺裸的)
做这道题,第一思路很重要,显然看到这题的第一想法就是ans=总数-不合法(不要问我为什么显然)。因为向这种用补集法的题一般都会给一些很奇葩的限制条件,但是一旦换个角度去想就很水了,好了不多说废话了。
显然,不合法的情况,也就是连续的回文区间的方案数,我们直接上Manacher就搞定了嘛!答案就是所有对称轴的(最长回文串长度+1)/2之和(是的,很显然)
对于不合法的情况,我们发现两串对称的情况跟卷积的形式类似(FFT做多了吧?),但是问题来了,怎么构造出一个卷积,使得它的值就是回文子串的个数呢?
我们发现原串只有a或b,所以思考能不能构造出一种卷积,使得对应位置的值跟下面一样
a*b->0 b*a->0 a*a->1 b*b->1
如果把a看成0,b看成1,这显然是一个异或,然而并没什么卵用。但我们如果把a看成0,b看成1,可以满足只有b*b是1,其他都是0;同理,把a看成1,b看成0,可以满足只有a*a是1,其他都是0,然后我们对这两种情况分别求一次卷积,就能得到:以i为对称中心的最长子序列的回文半径长度。这里注意一下,用于是两个一样的多项式相乘,所以每对字符会被算成两次(单个字符自我对称的除外),所以我们要的回文半径应该是(x+1)/2
然而半径长度并不是方案数,由于每对对称的字符都可以选或不选,所以对答案的贡献就是2^长度-1(因为你不能一个也不选吧?)
好吧,感觉说了这么多又有点说不明白了,所以欢迎提问和hack~
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#define pi acos(-1.0)
#define mod 1000000007
using namespace std;
int n,ans;
struct cp
{
double x,y;
cp (double a,double b){x=a,y=b;}
cp (){}
cp operator + (cp a){return cp(x+a.x,y+a.y);}
cp operator - (cp a){return cp(x-a.x,y-a.y);}
cp operator * (cp a){return cp(x*a.x-y*a.y,x*a.y+y*a.x);}
}n1[1<<20],n2[1<<20];
int s[1<<20],ret[1<<20],rl[1<<20],pn[1<<20];
char str[1<<20];
void FFT(cp *a,int len,int f)
{
int i,j,k,h;
cp t;
for(i=k=0;i<len;i++)
{
if(i>k) swap(a[i],a[k]);
for(j=(len>>1);(k^=j)<j;j>>=1);
}
for(h=2;h<=len;h<<=1)
{
cp wn(cos(f*2*pi/h),sin(f*2*pi/h));
for(j=0;j<len;j+=h)
{
cp w(1.0,0);
for(k=j;k<j+h/2;k++) t=w*a[k+h/2],a[k+h/2]=a[k]-t,a[k]=a[k]+t,w=w*wn;
}
}
}
void work(cp *a,cp *b,int len)
{
FFT(a,len,1),FFT(b,len,1);
for(int i=0;i<len;i++) a[i]=a[i]*b[i];
FFT(a,len,-1);
for(int i=0;i<len;i++) ret[i]+=(int)(a[i].x/len+0.1);
}
int main()
{
scanf("%s",str);
int i,mx,pos,len=strlen(str);
for(i=0;i<len;i++) s[n++]=0,s[n++]=str[i]-'a';
s[n++]=0;
for(mx=-1,i=0;i<n;i++)
{
if(mx>i) rl[i]=min(mx-i+1,rl[2*pos-i]);
else rl[i]=1;
for(;i+rl[i]<n&&rl[i]<=i&&s[i+rl[i]]==s[i-rl[i]];rl[i]++);
if(mx<i+rl[i]-1) mx=i+rl[i]-1,pos=i;
}
for(i=0;i<n;i++) ans=(ans-rl[i]/2+mod)%mod;
for(len=1;len<2*n;len<<=1);
for(i=0;i<len;i++) n1[i]=n2[i]=cp(0,0);
for(i=1;i<n;i+=2) n1[i]=n2[i]=cp(s[i],0);
work(n1,n2,len);
for(i=0;i<len;i++) n1[i]=n2[i]=cp(0,0);
for(i=1;i<n;i+=2) n1[i]=n2[i]=cp(s[i]^1,0);
work(n1,n2,len);
for(pn[0]=i=1;i<=n;i++) pn[i]=(pn[i-1]<<1)%mod;
for(i=0;i<n;i++) ans=(ans+pn[(ret[i<<1]+(i&1))>>1]-1)%mod;
printf("%d",ans);
return 0;
}
【BZOJ3160】万径人踪灭 Manacher+FFT的更多相关文章
- BZOJ3160 万径人踪灭(FFT+manacher)
容易想到先统计回文串数量,这样就去掉了不连续的限制,变为统计回文序列数量. 显然以某个位置为对称轴的回文序列数量就是2其两边(包括自身)对称相等的位置数量-1.对称有啥性质?位置和相等.这不就是卷积嘛 ...
- BZOJ3160 万径人踪灭 【fft + manacher】
题解 此题略神QAQ orz po神牛 由题我们知道我们要求出: 回文子序列数 - 连续回文子串数 我们记为ans1和ans2 ans2可以用马拉车轻松解出,这里就不赘述了 问题是ans1 我们设\( ...
- BZOJ3160: 万径人踪灭(FFT,回文自动机)
BZOJ传送门: 解题思路: FFT在处理卷积时可以将自己与自己卷,在某一种字母上标1其他标0,做字符集次就好了. (回文就是直接对称可以联系偶函数定义理解,根据这个性质就可以将字符串反向实现字符串匹 ...
- 【BZOJ3160】万径人踪灭(FFT,Manacher)
[BZOJ3160]万径人踪灭(FFT,Manacher) 题面 BZOJ 题解 很容易想到就是满足条件的子序列个数减去回文子串的个数吧... 至于满足条件的子序列 我们可以依次枚举对称轴 如果知道关 ...
- 【BZOJ3160】 万径人踪灭(FFT,manacher)
前言 多项式真的很难♂啊qwq Solution 考虑求的是一个有间隔的回文串,相当于是: 总的答案-没有间隔的答案 考虑总的答案怎么计算?FFT卷一下就好了. 对于每一位字符,有两种取值,然后随便卷 ...
- BZOJ3160:万径人踪灭(FFT,Manacher)
Solution $ans=$回文子序列$-$回文子串的数目. 后者可以用$manacher$直接求. 前者设$f[i]$表示以$i$为中心的对称的字母对数. 那么回文子序列的数量也就是$\sum_{ ...
- BZOJ3160 万径人踪灭 字符串 多项式 Manachar FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8810140.html 题目传送门 - BZOJ3160 题意 给你一个只含$a,b$的字符串,让你选择一个子序列 ...
- 万径人踪灭(FFT+manacher)
传送门 这题--我觉得像我这样的菜鸡选手难以想出来-- 题目要求求出一些子序列,使得其关于某个位置是对称的,而且不能是连续一段,求这样的子序列的个数.这个直接求很困难,但是我们可以先求出所有关于某个位 ...
- bzoj 3160: 万径人踪灭【FFT+manacher】
考虑正难则反,我们计算所有对称子序列个数,再减去连续的 这里减去连续的很简单,manacher即可 然后考虑总的,注意到关于一个中心对称的两点下标和相同(这样也能包含以空位为对称中心的方案),所以设f ...
随机推荐
- Python-文件修改器
#-*- coding: utf-8 -*- import os import sys import glob from PyQt4.QtGui import * from PyQt4.QtCore ...
- C# 遍历Dictionary并修改其中的Value
C#的Dictionary类型的值,知道key后,value可以修改吗?答案是肯定能修改的.我在遍历的过程中可以修改Value吗?答案是也是肯定能修改的,但是不能用For each循环.否则会报以下的 ...
- 深度学习之Matlab 转C++在iOS上測试CNN手型识别
1 前言 在上一篇Blog.我介绍了在iOS上执行CNN的一些方法. 可是,一般来说.我们须要一个性能强劲的机器来跑CNN,我们仅仅只是须要将得到的结果用于移动端. 之前在Matlab使用UFLDL的 ...
- git 清除历史
http://stackoverflow.com/questions/9683279/make-the-current-commit-the-only-initial-commit-in-a-git- ...
- hdu5719 Arrange
首先,根据题意可得B数组应是单调不升的,C数组是单调不降的. 可以发现A_1 = B_1 = C_1A1=B1=C1,所以如果B_1 \neq C_1B1≠C1无解. 进 ...
- 跟着百度学PHP[15]-会话控制session的工作机制
COOKIE和SESSION的两大区别: cookie是存储与客户端 session是存储与服务端 需要开启session的时候需要使用session_start开启,且session的开头不能拥有任 ...
- XSS绕过与防御总结
跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶意攻击者往Web页面里插 ...
- 恶习为什么难戒?因为你在HALT状态
幸福课 | 恶习为什么难戒?因为你在HALT状态 文 游识猷 饥饿(hungry).生气(angry).孤单(lonely).疲惫(tired)这4种状态,被称为HALT——这个词刚好是英 ...
- WebService 页面重定向错误
“/”应用程序中的服务器错误. 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败. xxx.xxx.xxx.xxx:xx 说明: 执行当前 Web 请求期间,出现未经处理的异常.请 ...
- R学习----数据类型
今天开始学习R语言了,没原因,就是想学 本人开发环境在ubuntu 16.04 LTS下 R命令提示符 终端直接输入R进入交互模式进行R学习.如下图 R脚本 # My first program in ...