%%%dkw
話說這是個**題來著...
考慮生成函式\(ogf\)
對於價值為\(v\)的物品,由於有\(10^5\)的件數,可以看做無限個
那麼,其生成函式為\(x^0 + x^ + x^ + ... = \frac\)
我們所需的答案即\([x^n] \prod \frac}\)
只需考慮求出\(a = \prod \frac}\)
自然地想到取對數
\(in(a) = \sum in(\frac})\)
不難發現
\(in(\frac) = - in(1 - x^v)\)
考慮用麥克勞林級數來模擬,那麼
由於\(in^(1 - x) = - \frac * (n - 1)!\)
\(-in(1 - x^v) = \sum \frac}\)
於是,我們可以直接列舉倍數,在\(o(m \log m)\)的時間內完成計算
最後只要\(o(m \log m)\)的\(exp\)一下即可
#include #include #include #include #include using namespace std;
#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)
#define gc getchar
inline int read()
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
}const int sid = 500050;
const int mod = 998244353;
int n, m;
int v[sid], f[sid], inv[sid], rev[sid], ans[sid];
inline int inc(int a, int b)
inline int dec(int a, int b)
inline int mul(int a, int b)
inline int fp(int a, int k)
inline void init(int maxn, int &n, int &lg)
inline void ntt(int *a, int n, int opt)
if(opt == -1)
}int ia[sid], ib[sid];
inline void inv(int *a, int *b, int n)
inv(a, b, n >> 1);
int n = 1, lg = 0; init(n + n, n, lg);
for(ri i = 0; i < n; i ++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
for(ri i = 0; i < n; i ++) ia[i] = ib[i] = 0;
for(ri i = 0; i < n; i ++) ia[i] = a[i], ib[i] = b[i];
ntt(ia, n, 1); ntt(ib, n, 1);
for(ri i = 0; i < n; i ++)
ia[i] = dec((ib[i] << 1) % mod, mul(ia[i], mul(ib[i], ib[i])));
ntt(ia, n, -1);
for(ri i = 0; i < n; i ++) b[i] = ia[i];
}inline void inv_init(int n)
inline void wf(int *a, int *b, int n)
inline void jf(int *a, int *b, int n)
int iv[sid], dx[sid];
inline void in(int *a, int *b, int n)
int inb[sid], fb[sid];
inline void exp(int *a, int *b, int n)
exp(a, b, n >> 1);
for(ri i = 0; i < n + n; i ++) inb[i] = fb[i] = 0;
in(b, inb, n);
int n = 1, lg = 0; init(n + n, n, lg);
for(ri i = 0; i < n; i ++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
for(ri i = 0; i < n; i ++) fb[i] = dec(a[i], inb[i]); fb[0] ++;
for(ri i = 0; i < n; i ++) inb[i] = b[i];
ntt(inb, n, 1); ntt(fb, n, 1);
for(ri i = 0; i < n; i ++) fb[i] = mul(fb[i], inb[i]);
ntt(fb, n, -1);
for(ri i = 0; i < n; i ++) b[i] = fb[i], b[i + n] = 0;}
inline void calc()
int main()
luogu4389 付公主的揹包
題目大意 現在有 n 個物品,每種物品體積為 v i 對任意 s in 1,m 求揹包恰好裝 s 體積的方案數 完全揹包問題 資料範圍 n,m leq 10 5 這道題,看到資料範圍就知道是生成函式。ans prod n frac 但是這個式子直接乘會tle,我們考慮進行優化。看見這個連乘的式子,應...
洛谷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...