• [P4721] 分治 FFT


    「题意」给定(g[0]=1),(g[1~n-1])求序列(f[i]=sum_{j=1}^i f[i-j]*g[j] , iin[1,n-1],f[0]=1)
    「分析」分治处理区间[l,r],先递归求出[l,mid],在统计[l,mid]对[mid+1,r]的贡献,可以发现

    [f[x]+=sum_{i=l}^{mid}f[i]*g[x-i] , xin[mid+1,r] ]

    拿卷积算,令(A[0,mid-l])=(f[l,mid]), (B[l,r-l])=(g[1,r-l]) ,(B[0]=0),设(C[i])=(A[i]*B[i-j]), 那么

    [f[x]+=sum f[i]*g[x-1]=sum A[i-l]*B[x-i]=C[x-l] ]

    套上ntt

    「代码」

    #include <bits/stdc++.h>
    using namespace std;
    const int N=4e5+10;
    const int P=998244353,G=3;
    
    int n,lmt,l,rev[N];
    int g[N],f[N],A[N],B[N];
    
    int qpow(int x,int y) {
        int c=1;
        for(; y; y>>=1,x=1LL*x*x%P)
            if(y&1) c=1LL*c*x%P;
        return c;
    }
    void init(int len) {
        for(lmt=1,l=0; lmt<len+len; lmt<<=1) l++;
        for(int i=0; i<lmt; ++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    }
    void numberTheoreticTransform(int a[N],int tp) {
        for(int i=0; i<lmt; ++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
        for(int m=1; m<lmt; m<<=1) {
            long long wm=qpow(G,(P-1)/(m<<1));
            if(tp==-1) wm=qpow(wm,P-2);
            for(int i=0; i<lmt; i+=(m<<1)) {
                long long w=1,tmp;
                for(int j=0; j<m; ++j,w=w*wm%P) {
                    tmp=w*a[i+j+m]%P;
                    a[i+j+m]=(a[i+j]-tmp+P)%P;
                    a[i+j]=(a[i+j]+tmp)%P;
                }
            }
        }
        if(tp==-1) {
            long long tmp=qpow(lmt,P-2);
            for(int i=0; i<lmt; ++i) a[i]=tmp*a[i]%P;
        }
    }
    void dfs(int l,int r) {
        if(l==r) return;
        int mid=(l+r)>>1;
        dfs(l,mid);
        init(r-l+1);
        for(int i=0; i<lmt; ++i) A[i]=B[i]=0;
        for(int i=l; i<=mid; ++i) A[i-l]=f[i];
        for(int i=0; i<=r-l; ++i) B[i]=g[i];
        numberTheoreticTransform(A,1);
        numberTheoreticTransform(B,1);
        for(int i=0; i<lmt; ++i) A[i]=1LL*A[i]*B[i]%P;
        numberTheoreticTransform(A,-1);
        for(int i=mid+1; i<=r; ++i) f[i]=(f[i]+A[i-l])%P;
        dfs(mid+1,r);
    }
    
    
    int main() {
        scanf("%d",&n);
        for(int i=1; i<n; ++i) scanf("%d",g+i);
        f[0]=1, dfs(0,n-1);
        for(int i=0; i<n; ++i) printf("%d ",f[i]);
        printf("
    ");
        return 0;
    }
    

    ubuntu的中括号怎么是这个鬼玩意儿//

  • 相关阅读:
    学习vim命令:“:w !sudo tee %”
    mac下安装和卸载软件
    很好用的在线markdown编辑器
    doc2vec 利用gensim 生成文档向量
    C语言经典算法100例-024-求数列的前20 项和,2/1,3/2,5/3,8/5...
    C语言经典算法100例-023-打印菱形
    C语言经典算法100例-022-乒乓球比赛名单问题
    C语言经典算法100例-021-猴子吃桃问题
    C语言经典算法100例-020-小球自由下落问题
    C语言经典算法100例-019-求完数
  • 原文地址:https://www.cnblogs.com/nosta/p/10242686.html
Copyright © 2020-2023  润新知