zoukankan      html  css  js  c++  java
  • BZOJ3160 万径人踪灭(FFT+manacher)

      容易想到先统计回文串数量,这样就去掉了不连续的限制,变为统计回文序列数量。

      显然以某个位置为对称轴的回文序列数量就是2其两边(包括自身)对称相等的位置数量-1。对称有啥性质?位置和相等。这不就是卷积嘛。那么就做完了。

      又写挂manacher,没救。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 270000
    #define P 1000000007
    int n,m,s[N],t,r[N],f[N],p[N],ans=0;
    const double PI=3.14159265358979324;
    struct complex
    {
        double x,y;
        complex operator +(const complex&a) const
        {
            return (complex){x+a.x,y+a.y};
        }
        complex operator -(const complex&a) const
        {
            return (complex){x-a.x,y-a.y};
        }
        complex operator *(const complex&a) const
        {
            return (complex){x*a.x-y*a.y,x*a.y+y*a.x};
        }
    }a[N],b[N];
    void DFT(int n,complex *a,int p)
    {
        for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
        for (int i=2;i<=n;i<<=1)
        {
            complex wn=(complex){cos(2*PI/i),p*sin(2*PI/i)};
            for (int j=0;j<n;j+=i)
            {
                complex w=(complex){1,0};
                for (int k=j;k<j+(i>>1);k++,w=w*wn)
                {
                    complex x=a[k],y=w*a[k+(i>>1)];
                    a[k]=x+y,a[k+(i>>1)]=x-y;
                }
            }
        }
    }
    void mul(int n,complex *a,complex *b)
    {
        for (int i=0;i<n;i++) a[i].y=a[i].x-b[i].x,a[i].x=a[i].x+b[i].x;
        DFT(n,a,1);
        for (int i=0;i<n;i++) a[i]=a[i]*a[i];
        DFT(n,a,-1);
        for (int i=0;i<n;i++) a[i].x=a[i].x/n/4;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3160.in","r",stdin);
        freopen("bzoj3160.out","w",stdout);
        const char LL[]="%I64d";
    #else
        const char LL[]="%lld";
    #endif
        char c=getchar();
        while (c=='a'||c=='b') s[n++]=c-96,c=getchar();
        m=n*2-1;
        t=1;while (t<m) t<<=1;
        for (int i=0;i<t;i++) r[i]=(r[i>>1]>>1)|(i&1)*(t>>1);
        for (int i=0;i<n;i++) a[i].x=b[i].x=s[i]-1;
        mul(t,a,b);
        for (int i=0;i<m;i++) f[i]=(int){a[i].x+0.5};
        for (int i=0;i<t;i++) a[i].x=a[i].y=b[i].x=b[i].y=0;
        for (int i=0;i<n;i++) a[i].x=b[i].x=2-s[i];
        mul(t,a,b);
        for (int i=0;i<m;i++) f[i]+=(int){a[i].x+0.5};
        for (int i=0;i<m;i++) f[i]=f[i]+1>>1;
        p[0]=1;
        for (int i=1;i<m;i++) p[i]=(p[i-1]<<1)%P;
        for (int i=0;i<m;i++) ans=(ans+p[f[i]]-1)%P;
        for (int i=m-1;~i;i--) s[i]=(i&1?0:s[i>>1]);
        for (int i=m;i;i--) s[i]=s[i-1];
        s[0]=s[++m]=0;
        memset(r,0,sizeof(r));
        r[0]=0;int x=0;
        for (int i=1;i<=m;i++)
        {
            if (x+r[x]>=i) r[i]=min(r[x-(i-x)],x+r[x]-i);
            while (i-r[i]-1>=0&&i+r[i]+1<=m&&s[i+r[i]+1]==s[i-r[i]-1]) r[i]++;
            if (i+r[i]>=x+r[x]) x=i;
        }
        for (int i=0;i<=m;i++) ans=(ans-(r[i]+1>>1)+P)%P;
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    CSS3 --- 盒子
    CSS3 --- 伪元素
    CSS3 --- 伪类结构
    CSS3 --- 选择器
    HTML5 --- 新增表单属性
    HTML5 --- 新增标签
    CSS --- 定位
    CSS---浮动造成的影响
    CSS---盒子模型
    CSS---样式属性
  • 原文地址:https://www.cnblogs.com/Gloid/p/9455180.html
Copyright © 2011-2022 走看看