luogu4389 付公主的揹包

2022-05-25 19:00:11 字數 3126 閱讀 7264

題目大意:現在有$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 #include3

#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 }

luogu4389

洛谷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 ...