BZOJ 3160: 万径人踪灭
3160: 万径人踪灭
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1263 Solved: 701
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
Source
分析:
求所有不连续回文子序列的个数,我们先去掉不连续这个条件,求出所有回文子序列的个数,然后减去回文子串的个数就是答案...
考虑怎么求回文子序列的个数,发现回文子序列是由若干个以同一位置为对称轴的对称字符对组成,所以我们计算出$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