luoguP4705 玩游戏

好好玩

即对于k∈[1,t] 求(ax+by)^k

以下图片均来自于:

在Ta的博客查看

 

二项式展开:

 设:

那么:

可以卷积了

求:

(PS:随机序列的0~k次方和,这是一个经典问题。)

我的思路:O(nk)暴力

神仙思路:求一个毫不沾边的东西,然后写两次,对应上系数。O(nlog^2n)

 

不妨考虑求A(x):

先求一个看起来毫不沾边的东西:

这个G成为了写两次的东西

解决问题的中轴和杠杆

 

利用

分治NTT+求Ln

现在已经写了一次

 

写第二次:

 

对于单独一项,采用Taylor展开,往多项式方向靠近

合起来:

交换顺序:

哇!

写第二次,

Taylor展开+交换求和号

对应系数直接相等

 

神仙神仙~!~~~!!~!

 

Code

多项式全家桶

const int N=1e5+5;
int n,m,K;
int a[N],b[N];
int A[N],B[N];
int c[N];
int jie[N],inv[N];
il Poly divi(int l,int r){
    if(l==r){
        Poly g;g.resize(2);g[0]=1;g[1]=c[l];return g;
    }
    int mid=(l+r)>>1;
    Poly L=divi(l,mid),R=divi(mid+1,r);
    return L*R;
}
void wrk(int *a,int *A,int n){    
    for(reg i=1;i<=n;++i) c[i]=a[i];
    Poly G=divi(1,n);
    // G.out();
    G.resize(K+4);
    G=Ln(G);   
    G.resize(K+1);
    // G.out();
    for(reg k=1;k<=K;++k){
        if((k+1)&1){
            A[k]=mod-mul(G[k],k);
        }else{
            A[k]=mul(G[k],k);
        }
    }
}
int main(){
    rd(n);rd(m);
    for(reg i=1;i<=n;++i){
        rd(a[i]);
    }
    for(reg i=1;i<=m;++i){
        rd(b[i]);
    }
    rd(K);
    wrk(a,A,n);
    wrk(b,B,m);
    A[0]=n;
    B[0]=m;
    // prt(A,0,K);
    // prt(B,0,K);

    Poly f,g;
    f.resize(K+1);g.resize(K+1);
    jie[0]=1;
    for(reg i=1;i<=K;++i) jie[i]=(ll)jie[i-1]*i%mod;
    inv[K]=qm(jie[K],mod-2);
    for(reg i=K-1;i>=0;--i) inv[i]=mul(inv[i+1],i+1);

    for(reg i=0;i<=K;++i){
        f[i]=mul(A[i],inv[i]);
        g[i]=mul(B[i],inv[i]);
    }
    f=f*g;
    for(reg i=1;i<=K;++i){
        ll ans=mul(jie[i],f[i]);
        ans=mul(ans,qm(mul(n,m),mod-2));
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2019-04-19 15:59  *Miracle*  阅读(139)  评论(0编辑  收藏  举报