BZOJ 3160 万径人踪灭
Description
Input
Output
Sample Input
Sample Output
HINT
先在串中两两之间插入#,形成新串s,主要是考虑中心不在列上
令$f[i]$表示以i为中心,两边为a或b且相同的对数
$f[i]=\sum_{x+y=i*2}[s[x]==s[y]]$
注意$s[x]s[y]$不能为#
发现这其实是一个卷积,于是FFT,求出f[i]
于是通过f[i]算出答案
$Ans=\sum_{i=1}^{n}2^{f[i]}-1$
因为不能连续,减去连续的回文串数,用manacher
但有几个细节:
每对(x,y)其实等价于(y,x),所以要除2
然而当s[i]不是#,实际上因为$i+i=2×i$
只算了一次,当s[i]不是#时,f[i]要-1再除2再+1
如果s[i]是#就直接除2
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<complex> 7 using namespace std; 8 typedef complex<double> dob; 9 typedef long long lol; 10 double pi=acos(-1.0); 11 const int NN=1000000; 12 int Mod=1000000007; 13 dob a[NN],b[NN]; 14 int lg,R[NN],n,tot,N,f[NN],pw[NN]; 15 lol ans; 16 char ch[NN],s[NN]; 17 int qpow(int x,int y) 18 { 19 int res=1; 20 while (y) 21 { 22 if (y&1) res=1ll*res*x%Mod; 23 x=1ll*x*x%Mod; 24 y>>=1; 25 } 26 return res; 27 } 28 void FFT(dob *A,int len,double o) 29 {int i,j,k; 30 for (i=0;i<len;i++) 31 if (i<R[i]) swap(A[i],A[R[i]]); 32 for (i=1;i<len;i<<=1) 33 { 34 dob wn(cos(pi/i),sin(o*pi/i)),x,y; 35 for (j=0;j<len;j+=(i<<1)) 36 { 37 dob w(1,0); 38 for (k=0;k<i;k++,w*=wn) 39 { 40 x=A[j+k];y=w*A[j+k+i]; 41 A[j+k]=x+y; 42 A[j+k+i]=x-y; 43 } 44 } 45 } 46 } 47 lol manacher() 48 {lol i,len[800001]; 49 lol mx=0,po=0; 50 lol as=0; 51 for (i=1;i<N;i++) 52 { 53 if (mx>i) 54 len[i]=min(mx-i,len[2*po-i]); 55 else len[i]=1; 56 while (i-len[i]>=0&&i+len[i]<=N&&s[i-len[i]]==s[i+len[i]]) len[i]++; 57 if (len[i]+i>mx) 58 { 59 po=i; 60 mx=len[i]+i; 61 } 62 if (s[i]!='#') as+=(len[i]-1)/2+1; 63 else as+=(len[i]-1)/2; 64 as%=Mod; 65 } 66 return as; 67 } 68 int main() 69 {int i,len; 70 scanf("%s",ch); 71 n=strlen(ch); 72 tot=-1; 73 for (i=0;i<n;i++) 74 { 75 s[++tot]='#'; 76 s[++tot]=ch[i]; 77 } 78 s[++tot]='#';s[++tot]='$'; 79 N=tot; 80 len=1; 81 while (len<=2*N) len*=2,lg++; 82 for (i=0;i<len;i++) 83 R[i]=(R[i>>1]>>1)|((i&1)<<(lg-1)); 84 for (i=0;i<len;i++) 85 a[i]=(double)(s[i]=='a'); 86 FFT(a,len,1); 87 for (i=0;i<len;i++) 88 b[i]=a[i]*a[i]; 89 for (i=0;i<len;i++) 90 a[i]=(double)(s[i]=='b'); 91 FFT(a,len,1); 92 for (i=0;i<len;i++) 93 b[i]+=a[i]*a[i]; 94 FFT(b,len,-1); 95 for (i=0;i<N;i++) 96 f[i]=((int)(b[i*2].real()/(double)len+0.5)-(s[i]!='#'))>>1; 97 pw[0]=1; 98 for (i=1;i<=n;i++) 99 pw[i]=pw[i-1]*2%Mod; 100 for (i=1;i<N;i++) 101 { 102 lol res=pw[f[i]]-1; 103 if (s[i]!='#') res=res*2%Mod+1; 104 ans+=res; 105 if (ans>=Mod) ans-=Mod; 106 } 107 printf("%lld\n",(ans-manacher()+Mod)%Mod); 108 }