【BZOJ 3160】 3160: 万径人踪灭 (FFT)

3160: 万径人踪灭

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 1440  Solved: 799

Description

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 }
View Code

【所以我现在会迭代打法了hhh

 

2017-04-13 18:42:35

posted @ 2017-04-13 18:42  konjak魔芋  阅读(192)  评论(0编辑  收藏  举报