传送门

其实只要多背一些常见生成函数就好说了。

生成函数暴力搞它,根据小学奥数生成函数基础知识,答案的生成函数就是$\prod\limits_{i}\left(\sum\limits_{n=0}^\infty x^{v_in}\right)$

我们还知道$\sum\limits_{n=0}^\infty x^{v_in}=\dfrac{1}{1-x^{v_i}}$。

于是问题成了求$\prod\limits_i\dfrac{1}{1-x^{v_i}}$。

这个连乘看起来很别扭,考虑取个$\ln$转加法:

$\sum\limits_i\ln\dfrac{1}{1-x^{v_i}}$

根据初中奥数泰勒公式或背式子,我们知道$\ln\dfrac{1}{1-x^d}=\sum\limits_{n=1}^\infty \dfrac{x^{dn}}{n}$:

$\sum\limits_i\sum\limits_{n=1}^\infty\dfrac{x^{v_in}}{n}$

多项式加法好做啊。不过直接枚举每个$v_i$的倍数不大行。看到枚举倍数想调和级数,考虑把$v_i$相同的物品一块处理,记$c_i$为$v_j=i$的数量,则$f_j=\sum\limits_{i|j}\dfrac{c_i}{j/i}$。

最后$\exp$回来,复杂度$O(n\log n)$。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>

#define maxn 530005
#define inf 0x3f3f3f3f

const int mod = 998244353;
const int g = 3;

using namespace std;

inline int read(){
    int x=0,y=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return y?-x:x;
}
inline int quickpow(int x,int y=mod-2){
    int ans=1;
    while(y){
        if(y&1)ans=1ll*x*ans%mod;
        x=1ll*x*x%mod,y>>=1;
    }
    return ans;
}
const int ig = quickpow(g);
int tr[maxn],inv[maxn];
inline int qm(int x){return x>=mod?x-mod:x;}
void NTT(int *f,int n,bool t){
    for(register int i=0;i<n;++i)if(i<tr[i])swap(f[i],f[tr[i]]);
    for(register int p=2;p<=n;p<<=1){
        int len=p>>1,o=quickpow(t?ig:g,(mod-1)/p);
        for(register int i=0;i<n;i+=p){
            int gen=1,cop;
            for(register int j=i;j<i+len;++j){
                cop=1ll*f[j+len]*gen%mod,gen=1ll*gen*o%mod;
                f[j+len]=qm(f[j]+mod-cop),f[j]=qm(f[j]+cop);
            }
        }
    }
    if(t)for(register int i=0;i<n;++i)f[i]=1ll*f[i]*inv[n]%mod;
}
int A[maxn],B[maxn];
void mul(int *a,int *b,int *c,int n,int lim){
    for(register int i=0;i<n;++i)A[i]=a[i],B[i]=b[i];
    int m=n<<1;
    n=1;
    while(n<m)n<<=1;
    for(register int i=0;i<n;++i)tr[i]=(tr[i>>1]>>1)|(i&1?n>>1:0);
    NTT(A,n,0),NTT(B,n,0);
    for(register int i=0;i<n;++i)A[i]=1ll*A[i]*B[i]%mod;
    NTT(A,n,1);
    for(register int i=0;i<lim;++i)c[i]=A[i];
    for(register int i=0;i<n;++i)A[i]=B[i]=0;
}
int invR[maxn],_invR[maxn];
void Inv(int *f,int *g,int n){
#define R invR
#define _R _invR
    int lim=2;
    R[0]=quickpow(f[0]);
    while(lim<n<<1){
        for(register int i=0;i<lim;++i)_R[i]=R[i],R[i]=f[i];
        for(register int i=0;i<lim<<1;++i)tr[i]=(tr[i>>1]>>1)|(i&1?lim:0);
        NTT(_R,lim<<1,0),NTT(R,lim<<1,0);
        for(register int i=0;i<lim<<1;++i)R[i]=1ll*qm(2+mod-1ll*R[i]*_R[i]%mod)*_R[i]%mod;
        NTT(R,lim<<1,1),lim<<=1;
        for(register int i=lim>>1;i<lim;++i)R[i]=0;
    }
    for(register int i=0;i<n;++i)g[i]=R[i];
    for(register int i=0;i<lim;++i)R[i]=_R[i]=0;
#undef R
#undef _R
}
void derivate(int *f,int *g,int n){
    for(register int i=1;i<n;++i)g[i-1]=1ll*f[i]*i%mod;
    g[n-1]=0;
}
void intergrate(int *f,int *g,int n){
    for(register int i=n;i;--i)g[i]=1ll*f[i-1]*inv[i]%mod;
    g[0]=0;
}
int lnR[maxn];
void ln(int *f,int *g,int n){
#define R lnR
    Inv(f,R,n),derivate(f,g,n),mul(R,g,g,n,n),intergrate(g,g,n);
    for(register int i=0;i<n;++i)R[i]=0;
#undef R
}
int expR[maxn],_expR[maxn];
void Exp(int *f,int *g,int n){
#define R expR
#define _R _expR
    int lim=2;
    R[0]=1;
    while(lim<n<<1){
        for(register int i=0;i<lim;++i)_R[i]=R[i];
        ln(_R,_R,lim);
        for(register int i=1;i<lim;++i)_R[i]=qm(f[i]+mod-_R[i]);
        _R[0]=1,mul(R,_R,R,lim,lim),lim<<=1;
    }
    for(register int i=0;i<n;++i)g[i]=R[i];
    for(register int i=0;i<lim;++i)R[i]=_R[i]=0;
#undef R
#undef _R
}
int c[maxn],f[maxn];
int main(){
    inv[1]=1;
    for(register int i=2;i<maxn;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    int n=read(),m=read();
    for(register int i=1;i<=n;++i)++c[read()];
    for(register int i=1;i<=m;++i){
        if(!c[i])continue;
        for(register int j=i;j<=m;j+=i)
            f[j]=qm(f[j]+1ll*c[i]*inv[j/i]%mod);
    }
    Exp(f,f,m+1);
    for(register int i=1;i<=m;++i)printf("%d\n",f[i]);
}