題目大意:現在有$n$個物品,每種物品體積為$v_i$,對任意$s\in [1,m]$,求揹包恰好裝$s$體積的方案數(完全揹包問題)。
資料範圍:$n,m\leq 10^5$
這道題,看到資料範圍就知道是生成函式。
$$ans=\prod_^n\frac}$$
但是這個式子直接乘會tle,我們考慮進行優化。
看見這個連乘的式子,應該是要上$\ln$.
$$ans=\exp(\sum_^n\ln(\frac}))$$
接下來的問題就是如何快速計算$\ln(\frac})$。
$$\ln(f(x))=\int f'f^dx$$
所以$$\ln(\frac)=\int\sum_^vix^*(1-x^v)dx$$
$$=\int(\sum_^vix^-\sum_^v(i-1)x^)dx$$
$$=\int(\sum_^vx^)dx$$
$$=\sum_^\fracx^$$
然後就可以直接代公式了。
1 #include2 #include3luogu4389#define rint register int
4using
namespace
std;
5 typedef long
long
ll;6
const
int n = 400003, p = 998244353, g = 3, gi = 332748118;7
intn, m, cnt[n], a[n];
8 inline int kasumi(int a, int
b)15
return
res;16}
17int
r[n];
18 inline void ntt(int *a, int limit, int
type)30}
31}32if(type == -1)37
}38intans[n];
39 inline void poly_inv(int *a, int
deg)
45 poly_inv(a, (deg + 1) >> 1
);46
int limit = 1, l = -1;47
while(limit <= (deg << 1))
48for(rint i = 1;i < limit;i ++)
49 r[i] = (r[i >> 1] >> 1) | ((i & 1) <
50for(rint i = 0;i < deg;i ++) tmp[i] =a[i];
51for(rint i = deg;i < limit;i ++) tmp[i] = 0
;52 ntt(tmp, limit, 1); ntt(ans, limit, 1
);53
for(rint i = 0;i < limit;i ++)
54 ans[i] = (2 - (ll) tmp[i] * ans[i] % p + p) % p * ans[i] %p;
55 ntt(ans, limit, -1
);56
for(rint i = deg;i < limit;i ++) ans[i] = 0;57
}58intln[n];
59 inline void get_ln(int *a, int
deg)
67for(rint i = 1;i < limit;i ++)
68 r[i] = (r[i >> 1] >> 1) | ((i & 1) <
69 ntt(ans, limit, 1); ntt(tmp, limit, 1
);70
for(rint i = 0;i < limit;i ++) ln[i] = (ll) ans[i] * tmp[i] %p;
71 ntt(ln, limit, -1
);72
for(rint i = deg + 1;i < limit;i ++) ln[i] = 0;73
for(rint i = deg;i;i --) ln[i] = (ll) ln[i - 1] * kasumi(i, p - 2) %p;
74for(rint i = 0;i < limit;i ++) tmp[i] = ans[i] = 0
;75 ln[0] = 0;76
}77intexp[n];
78 inline void get_exp(int *a, int
deg)
83 get_exp(a, (deg + 1) >> 1
);84
get_ln(exp, deg);
85for(rint i = 0;i < deg;i ++) ln[i] = (a[i] + (i == 0) - ln[i] + p) %p;
86int limit = 1, l = -1;87
while(limit <= (deg << 1))
88for(rint i = 1;i < limit;i ++)
89 r[i] = (r[i >> 1] >> 1) | ((i & 1) <
90 ntt(exp, limit, 1); ntt(ln, limit, 1
);91
for(rint i = 0;i < limit;i ++) exp[i] = (ll) exp[i] * ln[i] %p;
92 ntt(exp, limit, -1
);93
for(rint i = deg;i < limit;i ++) exp[i] = 0;94
for(rint i = 0;i < limit;i ++) ln[i] = ans[i] = 0;95
}96intmain()
103for(rint i = 1;i <= m;i ++)
108 get_exp(a, m + 1
);109
for(rint i = 1;i <= m;i ++)
110 printf("
%d\n
", exp[i]);
111 }
洛谷4389 付公主的揹包
洛谷 挺巧妙的題。對於每件物品可以看成無窮多個,揹包轉移可以寫成卷積的形式,對於質量為 v 的物品,寫成生成函式就是 f x sum x 然後有 1e5 個這樣的東西,乘起來就是答案,複雜度 o mn log n 但這樣顯然過不了,我們把上面的函式變一下 f x sum x frac 然後若干個乘起...
洛谷P4389 付公主的揹包
傳送門 有 n 類物品,每種物品體積為 v i 且都有無數多件。問你塞滿容量為 s 的揹包方案數,對於每個 s in 1,m m 給定且 leq 10 5 都求出方案數。答案對 998244353 取模。30 的資料,n,m leq 3000 60 的資料,純隨機生成 100 的資料,n,m leq...
洛谷P4389 付公主的揹包
題目大意 有 n n leqslant10 5 種物品,第 i 個物品體積為 v i 都有 10 5 件。給定 m m leqslant10 5 對於 s in 1,m 請你回答用這些商品恰好裝 s 體積的方案數 題解 by weng weijie 揹包問題模板 誤 對每個物品構造生成函式 f x ...