bzoj3160: 万径人踪灭
数组开小gg
fft乱搞就可以了。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9+7; const double pi=acos(-1.0); struct complex { double r,i; complex(){} complex(double R,double I){r=R,i=I;} friend complex operator +(complex x,complex y){return complex(x.r+y.r,x.i+y.i);} friend complex operator -(complex x,complex y){return complex(x.r-y.r,x.i-y.i);} friend complex operator *(complex x,complex y){return complex(x.r*y.r-x.i*y.i,x.r*y.i+x.i*y.r);} }A[410000]; int Re[410000]; void fft(complex *a,int n,int op) { for(int i=0;i<n;i++) if(i<Re[i])swap(a[i],a[Re[i]]); for(int i=1;i<n;i<<=1) { complex wn(cos(pi/i),sin(op*pi/i)); for(int j=0;j<n;j+=(i<<1)) { complex w(1,0); for(int k=0;k<i;k++,w=w*wn) { complex t1=a[j+k],t2=a[j+k+i]*w; a[j+k]=t1+t2;a[j+k+i]=t1-t2; } } } } int a[410000],d[410000]; void solve(int len) { len++; memset(A,0,sizeof(A)); for(int i=0;i<len;i++)A[i].r=double(a[i]); int n,m=len*2,L=0; for(n=1;n<=m;n*=2)L++; for(int i=1;i<=n;i++)Re[i]=(Re[i>>1]>>1)|((i&1)<<(L-1)); fft(A,n,1); for(int i=0;i<=n;i++)A[i]=A[i]*A[i]; fft(A,n,-1); for(int i=0;i<=n;i++)d[i]+=(int(A[i].r/double(n)+0.5)+1)/2; } char ss[410000]; int sa[410000],p[410000]; LL manacher(int n) { int len=0; sa[++len]=0; for(int i=1;i<=n;i++) sa[++len]=ss[i]-'a'+1, sa[++len]=0; int k=1;p[1]=1; for(int i=2;i<=len;i++) { int L=k-p[k]+1,R=k+p[k]-1; int j=k-(i-k); if(R>=i)p[i]=min(p[j],j-L+1); else p[i]=0; while(i-p[i]>0&&i+p[i]<=len&&sa[i+p[i]]==sa[i-p[i]])p[i]++; if(i+p[i]-1>k+p[k]-1)k=i; } LL ret=0; for(int i=1;i<=len;i++) if(i%2==1)ret=(ret+(p[i]-1)/2)%mod; else ret=(ret+p[i]/2)%mod; return ret; } LL quick_pow(LL A,LL p) { LL ret=1; while(p!=0) { if(p%2==1)ret=ret*A%mod; A=A*A%mod;p/=2; } return ret; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%s",ss+1); int n=strlen(ss+1); LL ddd=manacher(n); a[0]=0; for(int i=1;i<=n;i++)a[i]=ss[i]-'a'; solve(n); for(int i=1;i<=n;i++)a[i]^=1; solve(n); LL sum=0; for(int i=2;i<=n*2;i++) { sum=(sum+quick_pow(2,d[i])-1+mod)%mod; } printf("%lld\n",((sum-ddd)%mod+mod)%mod); return 0; }
pain and happy in the cruel world.