生活随笔
收集整理的這篇文章主要介紹了
P4389 付公主的背包(生成函数,多项式exp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
P4389 付公主的背包
考慮生成函數有:
∏i=1n11?xvi對其取對數得,∑i=1nln?11?xviF(x)=11?xv,G(x)=ln?F(x)G(x)=∫F′(x)F(x)dxG(x)=∫vxv?11?xvdxG(x)=∫∑n≥0vxvn+v?1dxG(x)=∑n≥0vxvn+vvn+vG(x)=∑n≥0xv(n+1)n+1G(x)=∑n≥1xvnn對于原式:∑i=1n∑j=1∞xvijj\prod_{i = 1} ^{n} \frac{1}{1 - x ^{v_i}}\\ 對其取對數得,\sum_{i = 1} ^{n} \ln \frac{1}{1 - x ^{v_i}}\\ F(x) = \frac{1}{1 - x ^ v}, G(x) = \ln F(x)\\ G(x) = \int \frac{F'(x)}{F(x)} dx\\ G(x) = \int \frac{v x ^{v - 1}}{1 - x ^ v} dx\\ G(x) = \int \sum_{n \geq 0} vx ^{vn + v - 1} dx\\ G(x) = \sum_{n \geq 0} \frac{v x ^{vn + v}}{vn + v}\\ G(x) = \sum_{n \geq 0} \frac{x ^{v(n + 1)}}{n + 1}\\ G(x) = \sum_{n \geq 1} \frac{x ^{vn}}{n}\\ 對于原式:\sum_{i = 1} ^{n} \sum_{j = 1} ^{\infty} \frac{x ^{v_i j}}{j}\\ i=1∏n?1?xvi?1?對其取對數得,i=1∑n?ln1?xvi?1?F(x)=1?xv1?,G(x)=lnF(x)G(x)=∫F(x)F′(x)?dxG(x)=∫1?xvvxv?1?dxG(x)=∫n≥0∑?vxvn+v?1dxG(x)=n≥0∑?vn+vvxvn+v?G(x)=n≥0∑?n+1xv(n+1)?G(x)=n≥1∑?nxvn?對于原式:i=1∑n?j=1∑∞?jxvi?j?
提前預處理出invinvinv,然后O(nlog?n)O(n \log n)O(nlogn)對vijv_i jvi?j項加上inv[j]inv[j]inv[j],再做一次(modxm+1)\pmod{x ^{m + 1}}(modxm+1)的,多項式expexpexp即可。
#include <bits/stdc++.h>using namespace std
;const int mod
= 998244353, inv2
= mod
+ 1 >> 1;namespace Quadratic_residue
{struct Complex
{int r
, i
;Complex(int _r
= 0, int _i
= 0) : r(_r
), i(_i
) {}};int I2
;Complex
operator * (const Complex
&a
, Complex
&b
) {return Complex((1ll * a
.r
* b
.r
% mod
+ 1ll * a
.i
* b
.i
% mod
* I2
% mod
) % mod
, (1ll * a
.r
* b
.i
% mod
+ 1ll * a
.i
* b
.r
% mod
) % mod
);}Complex
quick_pow(Complex a
, int n
) {Complex ans
= Complex(1, 0);while (n
) {if (n
& 1) {ans
= ans
* a
;}a
= a
* a
;n
>>= 1;}return ans
;}int get_residue(int n
) {mt19937
e(233);if (n
== 0) {return 0;}if(quick_pow(n
, (mod
- 1) >> 1).r
== mod
- 1) {return -1;}uniform_int_distribution
<int> r(0, mod
- 1);int a
= r(e
);while(quick_pow((1ll * a
* a
% mod
- n
+ mod
) % mod
, (mod
- 1) >> 1).r
== 1) {a
= r(e
);}I2
= (1ll * a
* a
% mod
- n
+ mod
) % mod
;int x
= quick_pow(Complex(a
, 1), (mod
+ 1) >> 1).r
, y
= mod
- x
;if(x
> y
) swap(x
, y
);return x
;}
}const int N
= 1e6 + 10;int r
[N
], inv
[N
], a
[N
], b
[N
], c
[N
], d
[N
], e
[N
], t
[N
], n
, m
;int quick_pow(int a
, int n
) {int ans
= 1;while (n
) {if (n
& 1) {ans
= 1ll * a
* ans
% mod
;}a
= 1ll * a
* a
% mod
;n
>>= 1;}return ans
;
}void get_r(int lim
) {for (int i
= 0; i
< lim
; i
++) {r
[i
] = (i
& 1) * (lim
>> 1) + (r
[i
>> 1] >> 1);}
}void get_inv(int n
) {inv
[1] = 1;for (int i
= 2; i
<= n
; i
++) {inv
[i
] = 1ll * (mod
- mod
/ i
) * inv
[mod
% i
] % mod
;}
}void NTT(int *f
, int lim
, int rev
) {for (int i
= 0; i
< lim
; i
++) {if (i
< r
[i
]) {swap(f
[i
], f
[r
[i
]]);}}for (int mid
= 1; mid
< lim
; mid
<<= 1) {int wn
= quick_pow(3, (mod
- 1) / (mid
<< 1));for (int len
= mid
<< 1, cur
= 0; cur
< lim
; cur
+= len
) {int w
= 1;for (int k
= 0; k
< mid
; k
++, w
= 1ll * w
* wn
% mod
) {int x
= f
[cur
+ k
], y
= 1ll * w
* f
[cur
+ mid
+ k
] % mod
;f
[cur
+ k
] = (x
+ y
) % mod
, f
[cur
+ mid
+ k
] = (x
- y
+ mod
) % mod
;}}}if (rev
== -1) {int inv
= quick_pow(lim
, mod
- 2);reverse(f
+ 1, f
+ lim
);for (int i
= 0; i
< lim
; i
++) {f
[i
] = 1ll * f
[i
] * inv
% mod
;}}
}void polyinv(int *f
, int *g
, int n
) {if (n
== 1) {g
[0] = quick_pow(f
[0], mod
- 2);return ;}polyinv(f
, g
, n
+ 1 >> 1);for (int i
= 0; i
< n
; i
++) {t
[i
] = f
[i
];}int lim
= 1;while (lim
< 2 * n
) {lim
<<= 1;}get_r(lim
);NTT(t
, lim
, 1);NTT(g
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {int cur
= (2 - 1ll * g
[i
] * t
[i
] % mod
+ mod
) % mod
;g
[i
] = 1ll * g
[i
] * cur
% mod
;t
[i
] = 0;}NTT(g
, lim
, -1);for (int i
= n
; i
< lim
; i
++) {g
[i
] = 0;}
}void polysqrt(int *f
, int *g
, int n
) {if (n
== 1) {g
[0] = Quadratic_residue
::get_residue(f
[0]);return ;}polysqrt(f
, g
, n
+ 1 >> 1);polyinv(g
, b
, n
);int lim
= 1;while (lim
< 2 * n
) {lim
<<= 1;}get_r(lim
);for (int i
= 0; i
< n
; i
++) {t
[i
] = f
[i
];}NTT(g
, lim
, 1);NTT(b
, lim
, 1);NTT(t
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {g
[i
] = (1ll * inv2
* g
[i
] % mod
+ 1ll * inv2
* b
[i
] % mod
* t
[i
] % mod
) % mod
;b
[i
] = t
[i
] = 0;}NTT(g
, lim
, -1);for (int i
= n
; i
< lim
; i
++) {g
[i
] = 0;}
}void derivative(int *a
, int *b
, int n
) {for (int i
= 0; i
< n
; i
++) {b
[i
] = 1ll * a
[i
+ 1] * (i
+ 1) % mod
;}
}void integrate(int *a
, int n
) {for (int i
= n
- 1; i
>= 1; i
--) {a
[i
] = 1ll * a
[i
- 1] * inv
[i
] % mod
;}a
[0] = 0;
}void polyln(int *f
, int *g
, int n
) {polyinv(f
, b
, n
);derivative(f
, g
, n
);int lim
= 1;while (lim
< 2 * n
) {lim
<<= 1;}get_r(lim
);NTT(g
, lim
, 1);NTT(b
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {g
[i
] = 1ll * g
[i
] * b
[i
] % mod
;b
[i
] = 0;}NTT(g
, lim
, -1);for (int i
= n
; i
< lim
; i
++) {g
[i
] = 0;}integrate(g
, n
);
}void polyexp(int *f
, int *g
, int n
) {if (n
== 1) {g
[0] = 1;return ;}polyexp(f
, g
, n
+ 1 >> 1);int lim
= 1;while (lim
< 2 * n
) {lim
<<= 1;}polyln(g
, d
, n
);for (int i
= 0; i
< n
; i
++) {t
[i
] = (f
[i
] - d
[i
] + mod
) % mod
;}t
[0] = (t
[0] + 1) % mod
;get_r(lim
);NTT(g
, lim
, 1);NTT(t
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {g
[i
] = 1ll * g
[i
] * t
[i
] % mod
;t
[i
] = d
[i
] = 0;}NTT(g
, lim
, -1);for (int i
= n
; i
< lim
; i
++) {g
[i
] = 0;}
}int vis
[N
];int main() {scanf("%d %d", &n
, &m
);get_inv(4 * m
);for (int i
= 1, v
; i
<= n
; i
++) {scanf("%d", &v
);vis
[v
]++;}for (int i
= 1; i
<= m
; i
++) {for (int j
= i
; j
<= m
; j
+= i
) {a
[j
] = (a
[j
] + 1ll * inv
[i
] * vis
[j
/ i
] % mod
) % mod
;}}polyexp(a
, e
, m
+ 1);for (int i
= 1; i
<= m
; i
++) {printf("%d\n", e
[i
]);}return 0;
}
總結
以上是生活随笔為你收集整理的P4389 付公主的背包(生成函数,多项式exp)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。