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

    前言

    多项式真的很难♂啊qwq

    Solution

    考虑求的是一个有间隔的回文串,相当于是:
    总的答案-没有间隔的答案

    考虑总的答案怎么计算?FFT卷一下就好了。
    对于每一位字符,有两种取值,然后随便卷起来,卷起来就是当前这一位之前与它相同的字符个数(这一位不能是‘0’,也就是被排斥的那一位)
    然后就可以轻松解决?
    是的。

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<complex>
    #define ll long long
    #define re register
    using namespace std;
    inline int gi(){
        int f=1,sum=0;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    const int maxn=2000010,Mod=1e9+7;
    const double Pi=acos(-1.0);
    char s[maxn];
    int len,N,M,p[maxn],r[maxn];
    ll f[maxn],tw[maxn],ans;
    complex<double>a[maxn],b[maxn];
    ll manacher(){
        s[len+len+1]='#';s[0]=' ';
        for(int i=len;i;i--){
            s[i*2]=s[i];s[i*2-1]='#';
        }
        int mx=0,id=0;
        for(int i=1;i<=len+len;i++){
            p[i]=mx>i?min(p[id*2-i],mx-i):1;
            while(s[p[i]+i]==s[i-p[i]])p[i]++;
            if(i+p[i]>mx){
                id=i;mx=i+p[i];
            }
        }
        ll ret=0;
        for(int i=1;i<=len+len;i++)
            ret=(ret+p[i]/2)%Mod;
        return ret;
    }
    void FFT(complex<double> *P,int opt)
    {
        for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
        for(int i=1;i<N;i<<=1)
        {
            complex<double> W(cos(Pi/i),opt*sin(Pi/i));
            for(int p=i<<1,j=0;j<N;j+=p)
            {
                complex<double> w(1,0);
                for(int k=0;k<i;++k,w*=W)
                {
                    complex<double> X=P[j+k],Y=P[i+j+k]*w;;
                    P[j+k]=X+Y;P[i+j+k]=X-Y;
                }
            }
        }
    }
    void work(char cc)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=1;i<=len;++i)a[i]=b[i]=s[i]==cc;
        FFT(a,1);FFT(b,1);
        for(int i=0;i<N;++i)a[i]*=b[i];
        FFT(a,-1);
        for(int i=1;i<N;++i)a[i].real()=a[i].real()/N+0.5;
        for(int i=0;i<=M;++i)f[i]+=((int)(a[i].real())+1)/2;
    }
    int main(){
        scanf("%s",s+1);len=strlen(s+1);
        M=len+len;tw[0]=1;
        for(int i=1;i<=M;i++)tw[i]=(tw[i-1]+tw[i-1])%Mod;
        int l=0;
        for(N=1;N<=M;N<<=1)l++;
        for(int i=0;i<N;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
        work('a');work('b');
        for(int i=1;i<=M;i++)ans=(ans+tw[f[i]]-1)%Mod;
        printf("%lld
    ",(ans-manacher()+Mod)%Mod);
        return 0;
    }
    
  • 相关阅读:
    【译】第33节---种子数据
    python文件的读写
    python-----实现数据库安装和连接操作
    学习进度(第三周)
    解 idea(.IntelliJIdea2019.3)双击打不开的原因
    python爬虫------处理cookie的相关请求
    安装retrying模块出现 (Retry(total=4, connect=None, read=None, redirect=None, status=None))
    java----统计疫情可视化展示--echarts(三)
    java----统计疫情可视化展示--echarts(二)
    java----统计疫情可视化展示--echarts
  • 原文地址:https://www.cnblogs.com/mleautomaton/p/10278236.html
Copyright © 2011-2022 走看看