• LOJ#6261. 一个人的高三楼 组合+NTT


    令 $f(i,j)$ 表示 $j$ 的 $i$ 阶前缀和.  

    那么有 $f(i,j)=sum_{j=1}^{i} f(i-1,j)$,这个可以直接多项式快速幂.  

    时间复杂度是 $O(n log^2 n)$  或 $O(n log n)$ ,但是常数大而且第二种不好写.    

    考虑计算每一个位置 $j leqslant i$ 对 $i$ 位置的贡献.  

    令 $p(i,j,k)$ 表示 $j$ 对 $i$ 的 $k$ 阶前缀和的贡献系数,那么有: 

    $p(i,j,k)=sum_{t=1}^{i} p(t,j,k-1)$.   

    组合意义上可以看作将 $j-i$ 分成 $k$ 份的方案数,即 $inom{j-i+k-1}{k-1}$.     

    构建生成函数 $B(x)=sum_{i=0}^{infty} inom{i+k-1}{i} x^i$ 然后和 $A(x)=sum_{i=0}^{n} a_{i} x^i$ 卷一下即可. 

    code: 

    #include <cstdio> 
    #include <cstring>  
    #include <algorithm>  
    #define N 400009
    #define ll long long 
    #define mod 998244353
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;        
    ll kth;  
    int A[N],B[N],inv[N],n;  
    int qpow(int x,int y) { 
        int tmp=1; 
        for(;y;y>>=1,x=(ll)x*x%mod)  
            if(y&1) tmp=(ll)tmp*x%mod;  
        return tmp;  
    }  
    int get_inv(int x) {  
        return qpow(x,mod-2); 
    }   
    void NTT(int *a,int len,int op) {  
        for(int i=0,k=0;i<len;++i) {  
            if(i>k) swap(a[i],a[k]); 
            for(int j=len>>1;(k^=j)<j;j>>=1); 
        }
        for(int l=1;l<len;l<<=1) {   
            int w=qpow(3,(mod-1)/(l<<1)),wn,x,y;   
            if(op==-1) w=get_inv(w);   
            for(int i=0;i<len;i+=l<<1) {    
                wn=1; 
                for(int j=0;j<l;++j) {    
                    x=a[i+j],y=(ll)a[i+j+l]*wn%mod;    
                    a[i+j]=(ll)(x+y)%mod;  
                    a[i+j+l]=(ll)(x-y+mod)%mod;    
                    wn=(ll)wn*w%mod;  
                }  
            }
        }     
        if(op==-1) {   
            int p=get_inv(len);  
            for(int i=0;i<len;++i) { 
                a[i]=(ll)a[i]*p%mod;  
            }
        }
    }     
    void init() { 
        inv[1]=1; 
        for(int i=2;i<N;++i) { 
            inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;  
        }     
        inv[0]=1;  
        for(int i=1;i<N;++i) {
            inv[i]=(ll)inv[i-1]*inv[i]%mod;  
        }
        ll mul=1;   
        for(int i=0;i<=n;++i) {   
            B[i]=(ll)mul%mod*inv[i]%mod;   
            mul=mul*1ll*((kth+i)%mod)%mod;    
        }
    }   
    int main() {  
        // setIO("input"); 
        scanf("%d%lld",&n,&kth);    
        init();  
        for(int i=1;i<=n;++i) scanf("%d",&A[i]);     
        int l=1;  
        for(;l<(2*n+1);l<<=1);  
        NTT(A,l,1),NTT(B,l,1); 
        for(int i=0;i<l;++i) {
            A[i]=(ll)A[i]*B[i]%mod; 
        }
        NTT(A,l,-1); 
        for(int i=1;i<=n;++i) {  
            printf("%d
    ",A[i]); 
        }
        return 0; 
    }
    

      

         

  • 相关阅读:
    粒子系统(二):绘制精美几何图案
    图像识别:微信跳一跳机器人
    粒子系统(一):从零开始画一颗树
    Unity3D对弈游戏:狼吃羊游戏
    编程模拟自然(九):元胞自动机
    自动绘图AI:程序如何画出动漫美少女
    UWP简单示例(三):快速开发2D游戏引擎
    jsoup开发网页客户端3
    Android 自定义Dialog类,并在Activity中实现按钮监听。
    Jsoup开发网站客户端第二篇,图片轮播,ScrollView兼容ListView
  • 原文地址:https://www.cnblogs.com/guangheli/p/13354115.html
Copyright © 2020-2023  润新知