Evanyou Blog 彩带
扩大
缩小

洛谷 P4705 玩游戏

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define rap(i,s,n) for(int i=s;i<=n;i++)
#define drap(i,n,s) for(int i=n;i>=s;i--)
#define N 410000
#define P 998244353
#define lb(x) ((x&(-x)))
#define ll long long
#define m(s,k) memset(s,k,sizeof s)
using namespace std;
char xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
#define isd(c) ((c>='0'&&c<='9')||(c=='-'))
template<typename T>
inline bool rd(T& xa){
    char xchh; T f=1; while(xchh=getc(),(!isd(xchh))&&(xchh!=0));
    if(xchh==0) return 0; if(xchh=='-') xchh=getc(),f=-1; xa=xchh-'0';
    while(xchh=getc(),isd(xchh)) xa=xa*10+xchh-'0'; xa*=f; return 1;
}
ll mpow(ll a,ll k,ll p){ll res=1; while(k){if(k&1) res=res*a%p; k>>=1; a=a*a%p;} return res%p;}
ll Inv(ll x){return mpow(x,P-2,P);}
ll fac[N],inv[N],finv[N];
void Finit(int n){
    fac[0]=1; rap(i,1,n) fac[i]=fac[i-1]*i%P;
    inv[1]=1; rap(i,2,n) inv[i]=inv[P%i]*(P-P/i)%P;
    finv[0]=1; rap(i,1,n) finv[i]=finv[i-1]*inv[i]%P;
}
namespace Poly{
    ll c[N],f[N],f1[N],fi[N];
    int rev[N],lim,l;
    void init(int n){
        lim=1,l=0; while(lim<=n) lim<<=1,l++;
        rap(i,1,lim-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    }
    void NTT(ll *A,int k){
        rap(i,1,lim-1) if(i<rev[i]) swap(A[i],A[rev[i]]); for(int l=1;l<lim;l<<=1){
            ll gn=mpow(3,(P-1)+k*(P-1)/l/2,P); for(int j=0;j<lim;j+=l*2){
                ll g=1; for(int k=0;k<l;k++,g=g*gn%P){
                    ll x=A[k+j],y=A[k+j+l]*g%P;
                    A[k+j]=(x+y)%P; A[k+j+l]=(x-y+P)%P;
                }
            }
        }
        if(k==-1) {ll tinv=Inv(lim); rap(i,0,lim-1) A[i]=A[i]*tinv%P;}
    }
    void MUL(ll *A,int n,ll *B,int m,ll *C){
        init(n+m); NTT(A,1); NTT(B,1); rap(i,0,lim-1) C[i]=A[i]*B[i]%P; NTT(A,-1); NTT(B,-1); NTT(C,-1);
    }
    void MUL(ll *A,int n,ll *B,int m){
        init(n+m); NTT(A,1); NTT(B,1); rap(i,0,lim-1) B[i]=B[i]*A[i]%P; NTT(A,-1); NTT(B,-1);
    }
    void INV(ll *A,ll *B,int n){
        if(n==1){B[0]=Inv(A[0]); return;} INV(A,B,(n+1)>>1);
        init(2*n); m(c,0); rap(i,0,n-1) c[i]=A[i]; NTT(c,1); NTT(B,1);
        rap(i,0,lim-1) B[i]=(2-B[i]*c[i]+P)%P*B[i]%P;
        NTT(B,-1); rap(i,n,lim-1) B[i]=0; return;
    }
    void MUL(ll *A,int *a,int n){
        int len=1; while(len<n) len<<=1; ll *f[N];
        rap(i,1,len){f[i]=new ll[lb(i)<<2]; f[i][0]=1; f[i][1]=a[i];}
        for(int l=1;l<len;l<<=1){init(2*l); for(int j=l*2;j<=len;j+=l*2){
            NTT(f[j-l],1); NTT(f[j],1);
            rap(i,0,lim-1) f[j][i]=f[j][i]*f[j-l][i]%P; NTT(f[j],-1);
        }}
        rap(i,0,n) A[i]=f[len][i];
        return;
    }
    void DEAL(ll *A,int *a,int n,int k){
        m(f,0); MUL(f,a,n); m(f1,0); rap(i,0,n-1) f1[i]=f[i+1]*(i+1)%P;
        m(fi,0); INV(f,fi,k+1); MUL(f1,n-1,fi,k,A); drap(i,k,1) A[i]=A[i-1]*inv[i]%P;
        rap(i,k+1,lim-1) A[i]=0;
        rap(i,1,k){A[i]=A[i]*i%P; if((i&1)==0) A[i]=P-A[i];}
    }
}
int n,m,K,a[N],b[N];
ll A[N],B[N],ans[N];
int main(){
    rd(n); rd(m); rap(i,1,n) rd(a[i]); rap(i,1,m) rd(b[i]); rd(K);
    Finit(max(max(n,m),K)+100);
    Poly::DEAL(A,a,n,K); Poly::DEAL(B,b,m,K);
    rap(i,1,K) A[i]=A[i]*finv[i]%P,B[i]=B[i]*finv[i]%P;
    A[0]=n; B[0]=m; Poly::MUL(A,K,B,K,ans);
    ll tinv=Inv(1ll*n*m%P); rap(i,1,K) ans[i]=ans[i]*fac[i]%P*tinv%P;
    rap(i,1,K) printf("%lld\n",ans[i]);
    return 0;
}

 

posted @ 2018-09-08 15:56  yi_heng  阅读(234)  评论(0编辑  收藏  举报