zoukankan      html  css  js  c++  java
  • 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
    ",((sum-ddd)%mod+mod)%mod);
        
        return 0;
    }
  • 相关阅读:
    mac 使用brew 安装php-redis
    thinkphp6 使用redis 实现消息队列
    Redis 桌面管理器:Another Redis Desktop Manager
    linux 查看并关闭shell脚本执行
    MySQL教程之concat以及group_concat的用法
    PHP redis 使用
    thinkphp6 command(自定义指令)
    git 使用
    linux shell中 "2>&1"含义
    linux crontab 定时任务
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10113519.html
Copyright © 2011-2022 走看看