luoguP4389 付公主的揹包 多項式exp

2022-04-30 05:57:10 字數 2779 閱讀 6537

%%%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...