bzoj3160: 万径人踪灭

数组开小gg

fft乱搞就可以了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7; 
const double pi=acos(-1.0);

struct complex
{
    double r,i;
    complex(){}
    complex(double R,double I){r=R,i=I;}
    friend complex operator +(complex x,complex y){return complex(x.r+y.r,x.i+y.i);}
    friend complex operator -(complex x,complex y){return complex(x.r-y.r,x.i-y.i);}
    friend complex operator *(complex x,complex y){return complex(x.r*y.r-x.i*y.i,x.r*y.i+x.i*y.r);}
}A[410000]; int Re[410000];
void fft(complex *a,int n,int op)
{
    for(int i=0;i<n;i++)
        if(i<Re[i])swap(a[i],a[Re[i]]);
        
    for(int i=1;i<n;i<<=1)
    {
        complex wn(cos(pi/i),sin(op*pi/i));
        for(int j=0;j<n;j+=(i<<1))
        {
            complex w(1,0);
            for(int k=0;k<i;k++,w=w*wn)
            {
                complex t1=a[j+k],t2=a[j+k+i]*w;
                a[j+k]=t1+t2;a[j+k+i]=t1-t2;
            }
        }
    }
}

int a[410000],d[410000];
void solve(int len)
{
    len++;
    memset(A,0,sizeof(A));
    for(int i=0;i<len;i++)A[i].r=double(a[i]);
    int n,m=len*2,L=0;
    for(n=1;n<=m;n*=2)L++;
    for(int i=1;i<=n;i++)Re[i]=(Re[i>>1]>>1)|((i&1)<<(L-1));
    
    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++)d[i]+=(int(A[i].r/double(n)+0.5)+1)/2;
}

char ss[410000];
int sa[410000],p[410000];
LL manacher(int n)
{
    int len=0; sa[++len]=0;
    for(int i=1;i<=n;i++)
        sa[++len]=ss[i]-'a'+1, sa[++len]=0;
    int k=1;p[1]=1;
    for(int i=2;i<=len;i++)
    {
        int L=k-p[k]+1,R=k+p[k]-1;
        int j=k-(i-k);
        if(R>=i)p[i]=min(p[j],j-L+1);
        else p[i]=0;
        
        while(i-p[i]>0&&i+p[i]<=len&&sa[i+p[i]]==sa[i-p[i]])p[i]++;
        if(i+p[i]-1>k+p[k]-1)k=i;
    }
    LL ret=0;
    for(int i=1;i<=len;i++)
        if(i%2==1)ret=(ret+(p[i]-1)/2)%mod;
        else ret=(ret+p[i]/2)%mod;
    return ret;
}

LL quick_pow(LL A,LL p) 
{
    LL ret=1;
    while(p!=0) 
    {
        if(p%2==1)ret=ret*A%mod;
        A=A*A%mod;p/=2;
    }
    return ret; 
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%s",ss+1); int n=strlen(ss+1);
    LL ddd=manacher(n); a[0]=0;
    for(int i=1;i<=n;i++)a[i]=ss[i]-'a'; solve(n);
    for(int i=1;i<=n;i++)a[i]^=1;         solve(n);
    
    LL sum=0;
    for(int i=2;i<=n*2;i++)
    {
        sum=(sum+quick_pow(2,d[i])-1+mod)%mod;
    }
    printf("%lld\n",((sum-ddd)%mod+mod)%mod);
    
    return 0;
}

 

posted @ 2018-12-13 13:41  AKCqhzdy  阅读(100)  评论(0编辑  收藏  举报