题目链接
这题乍一眼应该是个生成函数题
我们可以把体积转化成生成函数
f
(
x
)
=
[
x
f(x)=[x
f(x)=[x%
v
=
=
0
]
v==0]
v==0]
然后跑1e5次FFT就可以了
emmm,感觉有点不妙啊,1e5次FFT什么的好像肯定要T啊
我们感受下复杂度主要集中在卷积上面
因为求ln能化乘为加,所以可以对生成函数求一波ln康康
好的,发现很有规律
f
(
x
)
=
[
x
f(x)=[x
f(x)=[x%
v
=
=
0
]
∗
1
x
v==0]*\frac{1}{x}
v==0]∗x1
那么调和级数加一下,求exp就可以啦,至于相同项,肯定是出现几次加几倍喽
代码如下:
#include<bits/stdc++.h>
#define mod 998244353
#define gg 3
using namespace std;
int r[400040],n,v,cnt[200020];
long long inv[400040],tmp1[400040],tmp2[400040],tmp3[400040],ln[400040],f[400040],de[400040],in[400040],ex[400040];
long long kasumi(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void NTT(long long *a,int kd,int cnt)
{
int lim=1<<cnt;
for(int i=0;i<lim;i++)
{
if(i<r[i]) swap(a[i],a[r[i]]);
}
for(int mid=1;mid<lim;mid<<=1)
{
long long wn=kasumi(gg,(mod-1)/(mid<<1));
if(kd) wn=kasumi(wn,mod-2);
for(int i=0;i<lim;i+=(mid<<1))
{
long long w=1;
for(int j=0;j<mid;j++,w=w*wn%mod)
{
long long x=a[i+j];
long long y=a[i+j+mid]*w%mod;
a[i+j]=(x+y)%mod;
a[i+j+mid]=(x-y+mod)%mod;
}
}
}
if(kd)
{
long long invl=kasumi(lim,mod-2);
for(int i=0;i<lim;i++)
{
a[i]=a[i]*invl%mod;
}
}
}
void rev(int cnt)
{
int lim=1<<cnt;
for(int i=0;i<lim;i++)
{
r[i]=(r[i>>1]>>1)|((i&1)<<(cnt-1));
}
}
void der(const long long *a,int cnt)
{
int lim=1<<cnt;
for(int i=0;i<lim;i++)
{
de[i]=a[i+1]*(i+1)%mod;
}
}
void inte(const long long *a,int cnt)
{
int lim=1<<cnt;
for(int i=lim-1;i>=1;i--)
{
in[i]=a[i-1]*kasumi(i,mod-2)%mod;
}
}
void get_inv(const long long *a,int len)
{
int cnt=0;
for(int i=0;i<len;i++) tmp1[i]=tmp2[i]=inv[i]=0;
inv[0]=kasumi(a[0],mod-2);
int lim=1;
while(lim<len)
{
cnt++;
rev(cnt);
lim<<=1;
for(int i=0;i<lim>>1;i++)
{
tmp1[i]=inv[i];
tmp2[i]=a[i];
}
NTT(tmp1,0,cnt);NTT(tmp2,0,cnt);
for(int i=0;i<lim;i++)
{
tmp1[i]=(tmp1[i]*2ll%mod-tmp2[i]*tmp1[i]%mod*tmp1[i]%mod+mod)%mod;
}
NTT(tmp1,1,cnt);
for(int i=0;i<lim>>1;i++)
{
inv[i]=tmp1[i];
}
}
}
void get_ln(const long long *a,int len)
{
int lim=1,cnt=0;
while(lim<len) lim<<=1,cnt++;
get_inv(a,lim);
der(a,cnt);
NTT(inv,0,cnt); NTT(de,0,cnt);
for(int i=0;i<lim;i++) ln[i]=inv[i]*de[i]%mod;
NTT(ln,1,cnt);
inte(ln,cnt);
}
void get_exp(const long long *a,int len)
{
int cnt=1,lim=2;
ex[0]=1;
while(lim<len)
{
cnt++;
lim<<=1;
get_ln(ex,lim);
in[0]=0;
in[0]=(in[0]-1+mod)%mod;
for(int i=0;i<lim>>1;i++)
{
tmp1[i]=a[i];
tmp2[i]=mod-in[i];
tmp3[i]=ex[i];
}
for(int i=lim>>1;i<lim;i++) tmp1[i]=tmp2[i]=tmp3[i]=0;
NTT(tmp3,0,cnt);NTT(tmp1,0,cnt);NTT(tmp2,0,cnt);
for(int i=0;i<lim;i++)
{
tmp3[i]=tmp3[i]*((tmp2[i]+tmp1[i])%mod)%mod;
}
NTT(tmp3,1,cnt);
for(int i=0;i<lim>>1;i++)
{
ex[i]=tmp3[i];
}
}
}
int main()
{
int tmp;
scanf("%d%d",&n,&v);
for(int i=1;i<=n;i++)
{
scanf("%d",&tmp);
cnt[tmp]++;
}
for(int i=1;i<=v;i++)
{
if(cnt[i])
{
int tot=0;
for(int j=i;j<=v;j+=i)
{
f[j]=(f[j]+kasumi(++tot,mod-2)*cnt[i]%mod)%mod;
}
}
}
// for(int i=1;i<=10;i++) printf("%lld ",f[i]);
// puts("");
get_exp(f,(v+1)*2);
for(int i=1;i<=v;i++) printf("%lld\n",ex[i]);
}