大体思路
考虑生成函数
每一个物品的生成函数:
(egin{aligned}A(x)=sum_{i=0}x^{iv}=frac{1}{1-x^v}end{aligned})
(后面为其封闭形式)
答案:
(egin{aligned}zeta(x)=prod_{i=1}^nsum_{j=0}x^{v_i imes j}end{aligned})
时间复杂度 (Theta(nmlog m)),会 (TLE)。
把每一个物品的生成函数都卷起来时间复杂度吃不消——但是加起来是可以的。
考虑给(A(x))取个(ln),然后再(exp)回去。
设:
(F(x)=1-x^v,G(x)=ln F(x))
开始推式子:
(egin{aligned} G(x)&=ln F(x)\ G'(x)&=frac{F'(x)}{F(x)}\ G'(x)&=-frac{v imes x^{v-1}}{1-x^v}\ G'(x)&=-sum_{i=0}v imes x^{v-1} imes x^{iv}\ G'(x)&=-sum_{i=0}v imes x^{iv+v-1}\ G(x)&=-sum_{i=0}frac{v imes x^{v(i+1)}}{v imes(i+1)}\ G(x)&=-sum_{i=1}frac{x^{iv}}{i}\ ln A(x)&=sum_{i=1}frac{x^{iv}}{i} end{aligned})
有了这个式子,我们就可以很容易地将各物品的(ln)的和求出来了,然后再将求出来的式子进行(exp)还原即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5,mod=998244353;
int a[N],b[N],rev[N],inv[N],cnt[N],n,m,L,x;
int pow(int a,int b){
int res=1,c=a;
while (b){
if (b&1) res=1ll*res*c%mod;
b>>=1,c=1ll*c*c%mod;
}
return res;
}
void Get(int n,int opt=1){
L=opt?1:n;
while (L<n) L<<=1;
for (int i=1;i<L;i++) rev[i]=rev[i>>1]>>1|((i&1)?L>>1:0);
}
void fft(int *a,int opt){
for (int i=0;i<L;i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int l=2;l<=L;l<<=1){
int W=opt==1?pow(3,(mod-1)/l):pow(pow(3,(mod-1)/l),mod-2);
for (int i=0;i<L;i+=l)
for (int j=0,w=1;j<l>>1;j++,w=1ll*w*W%mod){
int x=a[i+j],y=1ll*a[i+j+l/2]*w%mod;
a[i+j]=(x+y)%mod,a[i+j+l/2]=(x-y)%mod;
}
}
if (opt==-1) for (int i=0,v=pow(L,mod-2);i<L;i++) a[i]=1ll*a[i]*v%mod;
}
void Qiud(int *f,int *g,int n){
f[n-1]=0;
for (int i=0;i<n-1;i++) f[i]=1ll*g[i+1]*(i+1)%mod;
}
void Jif(int *f,int *g,int n){
f[0]=0;
for (int i=1;i<n;i++) f[i]=1ll*g[i-1]*inv[i]%mod;
}
void Inv(int *f,int *g,int n){
int c[N];
f[0]=pow(g[0],mod-2);
for (int l=2;l<n<<1;l<<=1){
Get(l<<1,0);
for (int i=0;i<l;i++) c[i]=g[i];
for (int i=l;i<L;i++) c[i]=0;
fft(f,1),fft(c,1);
for (int i=0;i<L;i++) f[i]=(2-1ll*c[i]*f[i])%mod*f[i]%mod;
fft(f,-1);
for (int i=l;i<L;++i) f[i]=0;
}
}
void Ln(int *f,int *g,int n){
int c[N],d[N];
for (int i=0;i<n;i++) c[i]=d[i]=0;
Inv(c,g,n),Qiud(d,g,n);
Get(n<<1);
for (int i=n;i<L;i++) c[i]=d[i]=0;
fft(c,1),fft(d,1);
for (int i=0;i<L;i++) d[i]=1ll*c[i]*d[i]%mod;
fft(d,-1);
Jif(f,d,n);
}
void Exp(int *f,int *g,int n){
int c[N],d[N];
f[0]=1;
for (int l=2;l<n<<1;l<<=1){
Ln(d,f,l);
Get(l<<1,0);
for (int i=0;i<l;i++) c[i]=g[i];
for (int i=l;i<L;i++) c[i]=d[i]=0;
fft(f,1),fft(c,1),fft(d,1);
for (int i=0;i<L;i++) f[i]=(1ll-d[i]+c[i])*f[i]%mod;
fft(f,-1);
}
}
int main(){
inv[1]=1;
for (int i=2;i<=400000;i++) inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
scanf("%d%d",&n,&m);
for (int i=0;i<n;i++) scanf("%d",&x),++cnt[x];
for (int i=1;i<=m;i++)
if (cnt[i]){
for (int j=1;i*j<=m;j++)
a[i*j]=(1ll*a[i*j]+1ll*cnt[i]*inv[j]%mod)%mod;
}
Exp(b,a,m+1);
for (int i=1;i<=m;i++) b[i]=(b[i]+mod)%mod,printf("%d
",b[i]);
return 0;
}