Luogu4389.付公主的揹包
題意:
付公主有一個可愛的揹包qwq
這個揹包最多可以裝
大小的東西
付公主有
種商品,她要準備出攤了.
每種商品體積為
給定m,對於
資料範圍:
對於30%的資料,
對於60%的資料,純隨機生成
對於100%的資料,
對於100%的資料,
Analysis
首先每種物品都有
個,可以直接看成有無數個物品。考慮生成函式優化:對於任意一個
,設
。我們要求的就是所有這樣的函式的積。但是乘法不好做,我們考慮將
取
為
,最後
得到答案。
此時我們只需要將所有 累加起來,複雜度同篩法 ,最後多項式 就好。
Code
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;
const int N = 6e5 + 5;
const int mo = 998244353;
const int g = 3;
const int invg = (mo + 1) / 3;
typedef long long ll;
int A[N],B[N],c[N],d[N],e[N],f[N],w[N][2];
int rev[N],cnt[N],v[N],ans[N],inv[N];
int n,m,l,len;
inline int pow(int x,int p)
{
int ret = 1;
for (; p ; p >>= 1,x = (ll)x * x % mo)
if (p & 1) ret = (ll)ret * x % mo;
return ret;
}
inline void dft(int *f,int n,int opt)
{
for (len = 1,l = 0 ; len <= n ; len <<= 1,++l);
for (int i = 0 ; i < len ; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (l - 1));
for (int i = 0 ; i < len ; ++i) if (i < rev[i]) swap(f[i],f[rev[i]]);
for (int i = 1 ; i < len ; i <<= 1)
{
int wn = (~opt) ? w[i][0] : w[i][1];
for (int j = 0 ; j < len ; j += (i << 1))
{
int w = 1;
for (int k = 0 ; k < i ; ++k,w = (ll)w * wn % mo)
{
int x = (ll)f[j + k + i] * w % mo,y = f[j + k];
f[j + k] = (x + y) % mo,f[j + k + i] = (y - x + mo) % mo;
}
}
}
if (opt == -1)
{
int x = pow(len,mo - 2);
for (int i = 0 ; i < len ; ++i) f[i] = (ll)f[i] * x % mo;
}
}
inline void getinv(int *a,int *b,int n)
{
if (n == 1) { b[0] = pow(a[0],mo - 2); return; }
getinv(a,b,n >> 1);
for (int i = 0 ; i < n ; ++i) A[i] = a[i],B[i] = b[i];
dft(A,n << 1,1); dft(B,n << 1,1);
for (int i = 0 ; i < len ; ++i) A[i] = (ll)A[i] * B[i] % mo * B[i] % mo;
dft(A,n << 1,-1);
for (int i = 0 ; i < n ; ++i) b[i] = ((b[i] << 1) % mo - A[i] + mo) % mo;
for (int i = 0 ; i < len ; ++i) A[i] = B[i] = 0;
}
inline void getln(int *a,int *b,int n)
{
getinv(a,c,n);
for (int i = 0 ; i < n - 1 ; ++i) d[i] = (ll)(i + 1) * a[i + 1] % mo;
dft(c,n << 1,1); dft(d,n << 1,1);
for (int i = 0 ; i < len ; ++i) c[i] = (ll)c[i] * d[i] % mo;
dft(c,n << 1,-1);
for (int i = 1 ; i < n ; ++i) b[i] = (ll)inv[i] * c[i - 1] % mo;
for (int i = 0 ; i < len ; ++i) c[i] = d[i] = 0;
}
inline void getexp(int *a,int *b,int n)
{
if (n == 1) { b[0] = 1; return; }
getexp(a,b,n >> 1);
for (int i = 0 ; i < n ; ++i) e[i] = b[i];
getln(b,f,n);
for (int i = 0 ; i < n ; ++i) f[i] = (mo - f[i] + a[i]) % mo; f[0] = (f[0] + 1) % mo;
dft(e,n << 1,1); dft(f,n << 1,1);
for (int i = 0 ; i < len ; ++i) e[i] = (ll)e[i] * f[i] % mo;
dft(e,n << 1,-1);
for (int i = 0 ; i < n ; ++i) b[i] = e[i];
for (int i = 0 ; i < len ; ++i) e[i] = f[i] = 0;
}
int main()
{
scanf("%d%d",&n,&m); inv[1] = 1;
for (int i = 1 ; i <= n ; ++i)
{ int x; scanf("%d",&x); ++cnt[x]; }
int zs = 1; for (; zs <= m ; zs <<= 1);
for (int i = 1 ; i <= (zs << 1) ; i <<= 1) w[i][0] = pow(g,(mo - 1) / (i << 1)),w[i][1] = pow(invg,(mo - 1) / (i << 1));
for (int i = 2 ; i < zs ; ++i) inv[i] = (ll)(mo - mo / i) * inv[mo % i] % mo;
for (int i = 1 ; i <= m ; ++i)
if (cnt[i])
{
int del = (ll)i * cnt[i] % mo;
for (int j = 1 ; i * j <= m ; ++j) v[j * i] = (v[j * i] + del) % mo;
}
for (int i = 1 ; i <= m ; ++i) v[i] = (ll)inv[i] * v[i] % mo;
getexp(v,ans,zs);
for (int i = 1 ; i <= m ; ++i) printf("%d\n",ans[i]);
return 0;
}