【BZOJ 3160】 3160: 万径人踪灭 (FFT)
3160: 万径人踪灭
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 1440 Solved: 799Description
Input
Output
Sample Input
Sample Output
HINT
Source
【分析】
看题目被吓死,其实很多废话。。
还是自己想出来了。。FFT好强啊。。可以加速很多东西的说。
然后就是,枚举对称轴吧?
假设a[i]==a[j],那么用i+j表示它的对称轴。
共有0~2*n的对称轴,对于每个对称轴它的对称点对个数就是$F[k]=\sum s[k-i]==s[k+i]$
注意到只有a和b,假设只考虑a相同,令$a[i]=s[i]=='a'?1:0$
那么就是$F[k]=\sum a[k-i]*a[k+i]$
化成卷积形式,可以用FFT做了。用b也做一遍
最后答案是$\sum 2^{F[k]}$-空串-回文子串(不能连续嘛)
回文子串我用马拉车打了,,,然后打错了,,,然后TLE了,,,以为是FFT的递归版太慢,还去学了迭代打法【醉生梦死。。。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 #define Maxn 100010*8 9 #define Mod 1000000007 10 #define LL long long 11 const double pi=acos(-1); 12 13 int mymin(int x,int y) {return x<y?x:y;} 14 15 struct P 16 { 17 double x,y; 18 P() {x=y=0;} 19 P(double x,double y):x(x),y(y){} 20 friend P operator + (P x,P y) {return P(x.x+y.x,x.y+y.y);} 21 friend P operator - (P x,P y) {return P(x.x-y.x,x.y-y.y);} 22 friend P operator * (P x,P y) {return P(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);} 23 }a[Maxn]; 24 int i,j,k; 25 26 int nn=1,R[Maxn]; 27 void fft(P *a,int f) 28 { 29 for(i=0;i<nn;i++) if(i<R[i]) swap(a[i],a[R[i]]); 30 for(i=1;i<nn;i<<=1) 31 { 32 P wn(cos(pi/i),f*sin(pi/i)); 33 for(int ad=i<<1,j=0;j<nn;j+=ad) 34 { 35 P w(1,0); 36 for(k=0;k<i;k++,w=w*wn) 37 { 38 P x=a[j+k],y=w*a[j+k+i]; 39 a[j+k]=x+y;a[j+k+i]=x-y; 40 } 41 } 42 } 43 } 44 45 char s[Maxn]; 46 int ans[Maxn]; 47 48 int aa[Maxn],pp[Maxn]; 49 int get_manacher(int ll) 50 { 51 int mx=0,id=0; 52 for(int i=1;i<=ll;i++) 53 { 54 int k; 55 if(i<mx) k=mymin(pp[2*id-i],mx-i+1); 56 else k=1; 57 while(aa[i+k]==aa[i-k]&&i-k>=1&&i+k<=ll) k++; 58 pp[i]=k; 59 if(i+pp[i]-1>mx) mx=i+pp[i]-1,id=i; 60 } 61 int as=0; 62 for(int i=1;i<=ll;i+=2) as=(as+(pp[i]+1)/2)%Mod; 63 for(int i=2;i<=ll;i+=2) as=(as+pp[i]/2)%Mod; 64 return as; 65 } 66 67 int bin[Maxn]; 68 69 int main() 70 { 71 scanf("%s",s); 72 int n=strlen(s);n--; 73 for(i=0;i<=n;i++) a[i].x=(s[i]=='a'?1:0); 74 75 int ll=0;nn=1; 76 while(nn<=n+n) ll++,nn<<=1; 77 for(i=0;i<nn;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(ll-1)); 78 79 fft(a,1);for(i=0;i<=nn;i++) a[i]=a[i]*a[i];fft(a,-1); 80 for(i=0;i<=n+n;i++) ans[i]=(int)(a[i].x/nn+0.5); 81 82 for(i=0;i<=nn;i++) a[i].x=a[i].y=0; 83 for(i=0;i<=n;i++) a[i].x=(s[i]=='a'?0:1),a[i].y=0; 84 85 fft(a,1);for(i=0;i<=nn;i++) a[i]=a[i]*a[i];fft(a,-1); 86 for(i=0;i<=n+n;i++) ans[i]+=(int)(a[i].x/nn+0.5); 87 88 for(i=0;i<=n+n;i++) ans[i]=(ans[i]+1)/2; 89 int a1=0; 90 bin[0]=1;for(i=1;i<=n;i++) bin[i]=(bin[i-1]*2)%Mod; 91 for(i=0;i<=n+n;i++) a1=(a1+bin[ans[i]])%Mod; 92 a1-=n+n+1; 93 aa[0]=3;for(int i=0;i<=n;i++) aa[2*i+1]=s[i]-'a',aa[2*i+2]=2;aa[2*n+2]=5; 94 a1-=get_manacher(2*n+1); 95 a1=(a1%Mod+Mod)%Mod; 96 printf("%d\n",a1); 97 return 0; 98 }
【所以我现在会迭代打法了hhh
2017-04-13 18:42:35