# BZOJ 3160 万径人踪灭

Em 很长很长很啰嗦的题目

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long LL;
const int maxn=400010;
const int mod=1000000007;
const double pi=acos(-1.0);
int n;
int Num[32],cur,N,L;
int ch[maxn],tot,len,la;
int C[maxn],end[maxn];
int rev[maxn];
char s[maxn];
LL ans;
struct Node{
int len,fa,next[2];
}t[maxn];
struct cpx{
double r,i;
cpx(double r=0,double i=0):r(r),i(i){}
}A[maxn],tmp[maxn],x,y;
cpx operator +(const cpx &a,const cpx &b){return cpx(a.r+b.r,a.i+b.i);}
cpx operator -(const cpx &a,const cpx &b){return cpx(a.r-b.r,a.i-b.i);}
cpx operator *(const cpx &a,const cpx &b){return cpx(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);}
void init(){
ch[0]=-1;len=la=0;tot=1;
t[0].fa=t[1].fa=1;
t[0].len=0;t[1].len=-1;
for(N=1;N<n;N<<=1,L++);N<<=1,L++;
for(int i=0;i<N;++i){
cur=0;
for(int t=i;t;t>>=1)Num[++cur]=(t&1);
for(int j=1;j<=L;++j)rev[i]=(rev[i]<<1)+Num[j];
}return;
}
int Get_fa(int x){
while(ch[len-t[x].len-1]!=ch[len])x=t[x].fa;
return x;
}
ch[++len]=c;
int tmp=Get_fa(la);
if(!t[tmp].next[c]){
++tot;
t[tot].len=t[tmp].len+2;
t[tot].fa=t[Get_fa(t[tmp].fa)].next[c];
t[tmp].next[c]=tot;
//cout<<tot<<' '<<t[tot].fa<<endl;
//system("pause");
}la=t[tmp].next[c];end[la]++;
}
void Get_PAM(){
for(int i=tot;i>=1;--i){
end[t[i].fa]+=end[i];
ans=ans-end[i];
}ans%=mod;return;
}
LL pow_mod(LL v,LL p){
LL tmp=1;
while(p){
if(p&1)tmp=tmp*v%mod;
v=v*v%mod;p>>=1;
}return tmp;
}
void FFT(cpx *A,int n,int type){
for(int i=0;i<n;++i)tmp[i]=A[rev[i]];
for(int i=0;i<n;++i)A[i]=tmp[i];
for(int i=2;i<=n;i<<=1){
cpx wn(cos(2*pi/i),sin(2*pi/i)*type);
for(int j=0;j<n;j+=i){
cpx w(1,0);
for(int k=0;k<(i>>1);k++){
x=A[k+j];y=A[k+j+(i>>1)]*w;
A[k+j]=x+y;A[k+j+(i>>1)]=x-y;
w=w*wn;
}
}
}
if(type==-1)for(int i=0;i<n;++i)A[i].r/=n;
}
void Get_ans(char c){
for(int i=0;i<N;++i)A[i]=cpx();
for(int i=0;i<n;++i)if(s[i]==c)A[i].r=1.0;
FFT(A,N,1);
for(int i=0;i<N;++i)A[i]=A[i]*A[i];
FFT(A,N,-1);
for(int i=0;i<N;++i)C[i]=C[i]+(int)(A[i].r+0.5);
}
int main(){
scanf("%s",s);
n=strlen(s);
init();Get_PAM();
//cout<<"-1"<<endl;
Get_ans('a');Get_ans('b');
for(int i=0;i<N;++i){
ans=ans+pow_mod(2LL,(C[i]+1)>>1)-1;
ans%=mod;
}
printf("%lld\n",(ans+mod)%mod);
return 0;
}

posted @ 2016-03-29 15:27  _Vertical  阅读(223)  评论(2编辑  收藏  举报