luoguP4389 付公主的揹包 多項式exp
阿新 • • 發佈:2018-12-26
%%%dkw
話說這是個論文題來著...
考慮生成函式\(OGF\)
對於價值為\(v\)的物品,由於有\(10^5\)的件數,可以看做無限個
那麼,其生成函式為\(x^0 + x^{v} + x^{2v} + ... = \frac{1}{1 - x^v}\)
我們所需的答案即\([x^n] \prod \frac{1}{1 - x^{v_i}}\)
只需考慮求出\(A = \prod \frac{1}{1 - x^{v_i}}\)
自然地想到取對數
\(In(A) = \sum In(\frac{1}{1 - x^{v_i}})\)
不難發現
\(In(\frac{1}{1 - x^v}) = - In(1 - x^v)\)
考慮用麥克勞林級數來模擬,那麼
由於\(In^{(n)}(1 - x) = - \frac{1}{(1 - x)^n} * (n - 1)!\)
\(-In(1 - x^v) = \sum \frac{x^{vi}}{i}\)
於是,我們可以直接列舉倍數,在\(O(m \log m)\)的時間內完成計算
最後只要\(O(m \log m)\)的\(exp\)一下即可
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> 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() { int p = 0, w = 1; char c = gc(); while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); } 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) { return (a + b >= mod) ? a + b - mod : a + b; } inline int Dec(int a, int b) { return (a - b < 0) ? a - b + mod : a - b; } inline int mul(int a, int b) { return 1ll * a * b % mod; } inline int fp(int a, int k) { int ret = 1; for( ; k; k >>= 1, a = mul(a, a)) if(k & 1) ret = mul(ret, a); return ret; } inline void init(int Maxn, int &n, int &lg) { n = 1; lg = 0; while(n < Maxn) n <<= 1, lg ++; } inline void NTT(int *a, int n, int opt) { for(ri i = 0; i < n; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]); for(ri i = 1; i < n; i <<= 1) for(ri j = 0, g = fp(3, (mod - 1) / (i << 1)); j < n; j += (i << 1)) for(ri k = j, G = 1; k < i + j; k ++, G = mul(G, g)) { int x = a[k], y = mul(G, a[i + k]); a[k] = (x + y >= mod) ? x + y - mod : x + y; a[i + k] = (x - y < 0) ? x - y + mod : x - y; } if(opt == -1) { int ivn = fp(n, mod - 2); reverse(a + 1, a + n); rep(i, 0, n) a[i] = mul(a[i], ivn); } } int ia[sid], ib[sid]; inline void Inv(int *a, int *b, int n) { if(n == 1) { b[0] = fp(a[0], mod - 2); return; } 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) { inv[0] = inv[1] = 1; rep(i, 2, n) inv[i] = mul(inv[mod % i], mod - mod / i); } inline void wf(int *a, int *b, int n) { for(ri i = 1; i < n; i ++) b[i - 1] = mul(a[i], i); } inline void jf(int *a, int *b, int n) { for(ri i = 1; i < n; i ++) b[i] = mul(a[i - 1], inv[i]); } int iv[sid], dx[sid]; inline void In(int *a, int *b, int n) { for(ri i = 0; i < n + n; i ++) iv[i] = dx[i] = 0; Inv(a, iv, n); wf(a, dx, 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)); NTT(iv, N, 1); NTT(dx, N, 1); for(ri i = 0; i < N; i ++) iv[i] = mul(iv[i], dx[i]); NTT(iv, N, -1); jf(iv, b, n); } int inb[sid], fb[sid]; inline void Exp(int *a, int *b, int n) { if(n == 1) { b[0] = 1; return; } 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 N = 1, lg = 0; init(m + 5, N, lg); Inv_init(N); for(ri i = 1; i <= m; i ++) for(ri j = i; j <= m; j += i) F[j] = Inc(F[j], mul(V[i], inv[j / i])); Exp(F, ans, N); rep(i, 1, m) printf("%d\n", ans[i]); } int main() { n = read(); m = read(); rep(i, 1, n) V[read()] ++; calc(); return 0; }