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 }

 

posted @ 2018-01-30 15:24  Z-Y-Y-S  阅读(211)  评论(0编辑  收藏  举报