您的位置:首页 > 其它

BZOJ 3160: 万径人踪灭

2017-03-15 18:49 295 查看

3160: 万径人踪灭

Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 1263 Solved: 701
[Submit][Status][Discuss]

Description





Input



Output

Sample Input

Sample Output

HINT



Source

2013湖北互测week1

分析:

求所有不连续回文子序列的个数,我们先去掉不连续这个条件,求出所有回文子序列的个数,然后减去回文子串的个数就是答案...

考虑怎么求回文子序列的个数,发现回文子序列是由若干个以同一位置为对称轴的对称字符对组成,所以我们计算出$g[i]$代表以$i$为对称轴的对称字符对的个数$(i$代表的是倍增之后的字符串...$)$,然后$2^{g[i]}-1$就是$f[i]$...

那么观察发现,每一对对称字符对的下标加起来是对称轴在倍增之后的字符串中的下标...诶,这就很好办了...$FFT$一发就计算出了答案...

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<complex>
#include<cstdio>
//by NeighThorn
#define pi acos(-1)
using namespace std;

const int maxn=500000+5,mod=1e9+7;
typedef complex<double> M;

int n,m,L,ans,len,R[maxn],p[maxn];

M a[maxn],f[maxn],g[maxn];

char s[maxn],str[maxn];

inline int power(int x,int y){
int res=1;
while(y){
if(y&1)
res=1LL*res*x%mod;
x=1LL*x*x%mod,y>>=1;
}
return res;
}

inline void FFT(M *a,int f){
for(int i=0;i<n;i++)
if(i>R[i]) swap(a[i],a[R[i]]);
for(int i=1;i<n;i<<=1){
M wn(cos(pi/i),f*sin(pi/i));
for(int j=0;j<n;j+=(i<<1)){
M w(1,0);
for(int k=0;k<i;k++,w*=wn){
M x=a[j+k],y=w*a[j+k+i];
a[j+k]=x+y,a[j+k+i]=x-y;
}
}
}
if(f==-1)
for(int i=0;i<n;i++)
a[i]/=n;
}

inline void prework(void){
str[0]='$';int i;
for(i=0;s[i];i++)
str[2*i+1]='#',str[2*(i+1)]=s[i];
len=2*i+1,str[len]=str[len+1]='#';
}

inline void manacher(void){
int id,mx=0;
for(int i=1;i<len;i++){
p[i]=i<mx?min(p[id*2-i],mx-i):1;
while(str[i-p[i]]==str[i+p[i]])
p[i]++;
if(p[i]+i>mx)
id=i,mx=p[i]+i;
}
for(int i=1;i<len;i++)
ans=((ans-p[i]/2)%mod+mod)%mod;
}

signed main(void){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
scanf("%s",s);prework();m=len;
for(n=1;n<=m;n<<=1) L++;
for(int i=0;i<n;i++)
R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
manacher();
for(int i=0;s[i];i++)
if(s[i]=='a') a[i]=1;
FFT(a,1);
for(int i=0;i<n;i++) f[i]=a[i]*a[i],a[i]=0;
FFT(f,-1);
for(int i=0;s[i];i++)
if(s[i]=='b') a[i]=1;
FFT(a,1);
for(int i=0;i<n;i++) g[i]=a[i]*a[i];
FFT(g,-1);
for(int i=0,x;i<n;i++)
x=f[i].real()+g[i].real()+0.1,x=(x+1)>>1,ans=(ans+power(2,x)-1)%mod;
printf("%d\n",(ans+mod)%mod);
return 0;
}


  

By NeighThorn
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: