bzoj3160 万径人踪灭
正解:$FFT+manacher$。
这题写得蛋疼。。主要是$manacher$有一个地方写错调了好久。。还有我的计数方法好像跟网上的有点不一样,感觉自己在搞容斥原理一样。。
我们考虑设$f[i]$为i两边对称的字符对数。例如,$s=aabba$,则$f[3]=1$(下标从1开始)。然后我们发现这个其实很好算。如果$s[i]==s[j]$,那么它必然会对$f[(i+j)/2]$产生贡献。于是我们可以发现,$f[i]=\sum_{x+y=i*2}[s[x]==s[y]]$。然后这个肯定是可以用$FFT$跑的,我们对于$a$跑一次$FFT$,对于$b$再跑一次$FFT$。注意整个方案数会多算一次,$i+i=2*i$的情况也会算一次。最终答案就是$Ans=\sum_{i=1}^{n}2^{f[i]}-1$,然后再减去连续的子序列。连续的子序列我们用一遍$manacher$算出来就行了,然后又是一波容斥。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define rhl (1000000007) 15 #define NN (1000010) 16 #define inf (1<<30) 17 #define pi acos(-1) 18 #define il inline 19 #define RG register 20 #define ll long long 21 #define C complex <double> 22 23 using namespace std; 24 25 int p[NN],f[NN],bin[NN],rev[NN],n,nn,N,lg; 26 char s[NN],c[NN]; 27 C a[NN],b[NN]; 28 ll ans,res; 29 30 il int gi(){ 31 RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 32 if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; 33 } 34 35 il ll manacher(){ 36 RG int id=1,mx=1; RG ll ans=0; p[1]=1; 37 for (RG int i=2;i<nn;++i){ 38 if (i<mx) p[i]=min(p[(id<<1)-i],mx-i); else p[i]=1; 39 while (i-p[i]>=0 && s[i+p[i]]==s[i-p[i]]) p[i]++; 40 if (mx<i+p[i]) mx=i+p[i],id=i; 41 ans+=(p[i]>>1); if (s[i]!='#') ans--; 42 } 43 return ans%rhl; 44 } 45 46 il void fft(C *a,RG int n,RG int f){ 47 for (RG int i=0;i<n;++i) if (i<rev[i]) swap(a[i],a[rev[i]]); 48 for (RG int i=1;i<n;i<<=1){ 49 C wn(cos(pi/i),sin(f*pi/i)),x,y; 50 for (RG int j=0;j<n;j+=(i<<1)){ 51 C w(1,0); 52 for (RG int k=0;k<i;++k,w*=wn){ 53 x=a[j+k],y=w*a[j+k+i]; 54 a[j+k]=x+y,a[j+k+i]=x-y; 55 } 56 } 57 } 58 return; 59 } 60 61 il void work(){ 62 scanf("%s",c+1),n=strlen(c+1); s[0]='#'; 63 for (RG int i=1;i<=n;++i) s[i<<1]='#',s[(i<<1)-1]=c[i]; 64 nn=(n<<1)+1,s[nn]='&'; for (N=1;N<=(nn<<1);N<<=1) lg++; 65 for (RG int i=0;i<=N;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1)); 66 for (RG int i=0;i<N;++i) a[i]=s[i]=='a'; fft(a,N,1); 67 for (RG int i=0;i<N;++i) b[i]=a[i]*a[i],a[i]=s[i]=='b'; 68 fft(a,N,1); for (RG int i=0;i<N;++i) b[i]+=a[i]*a[i]; fft(b,N,-1); 69 bin[0]=1; for (RG int i=1;i<=nn;++i){ bin[i]=bin[i-1]<<1; if (bin[i]>=rhl) bin[i]-=rhl; } 70 for (RG int i=1;i<nn;++i){ 71 f[i]=((int)(b[i<<1].real()/N+0.5)-(s[i]!='#'))>>1; 72 res=bin[f[i]]-1; if (s[i]!='#') ans+=2*res; else ans+=res; 73 if (ans>=rhl) ans-=rhl; 74 } 75 printf("%lld\n",(ans-manacher()+rhl)%rhl); return; 76 } 77 78 int main(){ 79 work(); 80 return 0; 81 }