Skip to content

Commit 3998aeb

Browse files
committed
add
1 parent 987abae commit 3998aeb

17 files changed

+222
-57
lines changed

convolution/intmod.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
namespace ConvolutionIntMod {
77
using ll = long long;
8-
const ll Mod1 = 754974721;
9-
const ll Mod2 = 167772161;
10-
const ll Mod3 = 469762049;
11-
const ll M1invM2 = 95869806;
12-
const ll M12invM3 = 187290749;
8+
static constexpr ll Mod1 = 754974721;
9+
static constexpr ll Mod2 = 167772161;
10+
static constexpr ll Mod3 = 469762049;
11+
static constexpr ll M1invM2 = 95869806;
12+
static constexpr ll M12invM3 = 187290749;
1313
using M1 = ModInt<Mod1>;
1414
using M2 = ModInt<Mod2>;
1515
using M3 = ModInt<Mod3>;

convolution/mod2_64.hpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#pragma once
2+
3+
#include "modint/modint.hpp"
4+
#include "fft/ntt.hpp"
5+
#include "math/util.hpp"
6+
7+
namespace ConvolutionMod2_64 {
8+
using ull = unsigned long long;
9+
static constexpr ull M1 = 645922817;
10+
static constexpr ull M2 = 754974721;
11+
static constexpr ull M3 = 880803841;
12+
static constexpr ull M4 = 897581057;
13+
static constexpr ull M5 = 998244353;
14+
static constexpr ull M12M4 = M1 * M2 % M4;
15+
static constexpr ull M12M5 = M1 * M2 % M5;
16+
static constexpr ull M123M5 = M12M5 * M3 % M5;
17+
static constexpr ull M12 = M1 * M2;
18+
static constexpr ull M123 = M12 * M3;
19+
static constexpr ull M1234 = M123 * M4;
20+
static constexpr ull I2 = Math::inv_mod(M1, M2);
21+
static constexpr ull I3 = Math::inv_mod(M1 * M2 % M3, M3);
22+
static constexpr ull I4 = Math::inv_mod(M1 * M2 % M4 * M3 % M4, M4);
23+
static constexpr ull I5 = Math::inv_mod(M1 * M2 % M5 * M3 % M5 * M4 % M5, M5);
24+
25+
using mint1 = ModInt<M1>;
26+
using mint2 = ModInt<M2>;
27+
using mint3 = ModInt<M3>;
28+
using mint4 = ModInt<M4>;
29+
using mint5 = ModInt<M5>;
30+
31+
NTT<mint1> ntt1;
32+
NTT<mint2> ntt2;
33+
NTT<mint3> ntt3;
34+
NTT<mint4> ntt4;
35+
NTT<mint5> ntt5;
36+
37+
template <class mint>
38+
vector<mint> inner_mult(const vector<ull>& a, const vector<ull>& b, NTT<mint>& ntt) {
39+
constexpr unsigned int mod = mint::get_mod();
40+
vector<mint> a1(a.size()), b1(b.size());
41+
for (int i = 0; i < a.size(); i++) a1[i] = a[i] % mod;
42+
for (int i = 0; i < b.size(); i++) b1[i] = b[i] % mod;
43+
mint c = ntt.multiply(a1, b1)[0];
44+
return ntt.multiply(a1, b1);
45+
}
46+
template <class mint>
47+
vector<mint> inner_middle_prod(const vector<ull>& a, const vector<ull>& b, NTT<mint>& ntt) {
48+
constexpr unsigned int mod = mint::get_mod();
49+
vector<mint> a1(a.size()), b1(b.size());
50+
for (int i = 0; i < a.size(); i++) a1[i] = a[i] % mod;
51+
for (int i = 0; i < b.size(); i++) b1[i] = b[i] % mod;
52+
return ntt.middle_product(a1, b1);
53+
}
54+
vector<ull> multiply(const vector<ull>& a, const vector<ull>& b) {
55+
if (a.empty() || b.empty()) return {};
56+
auto c1 = inner_mult(a, b, ntt1);
57+
auto c2 = inner_mult(a, b, ntt2);
58+
auto c3 = inner_mult(a, b, ntt3);
59+
auto c4 = inner_mult(a, b, ntt4);
60+
auto c5 = inner_mult(a, b, ntt5);
61+
vector<ull> c(a.size() + b.size() - 1, 0);
62+
for (int i = 0; i < c.size(); i++) {
63+
ull y1 = c1[i].val();
64+
ull y2 = (c2[i].val() + M2 - y1) * I2 % M2;
65+
ull y3 = (c3[i].val() + M3 - (y1 + y2 * M1) % M3) * I3 % M3;
66+
ull y4 = (c4[i].val() + M4 - (y1 + y2 * M1 + y3 * M12M4) % M4) * I4 % M4;
67+
ull y5 = (c5[i].val() + M5 - (y1 + y2 * M1 + y3 * M12M5 + y4 * M123M5) % M5) * I5 % M5;
68+
c[i] = y1 + y2 * M1 + y3 * M12 + y4 * M123 + y5 * M1234;
69+
}
70+
return c;
71+
}
72+
vector<ull> middle_product(const vector<ull>& a, const vector<ull>& b) {
73+
if (b.empty() || a.size() > b.size()) return {};
74+
auto c1 = inner_middle_prod(a, b, ntt1);
75+
auto c2 = inner_middle_prod(a, b, ntt2);
76+
auto c3 = inner_middle_prod(a, b, ntt3);
77+
auto c4 = inner_middle_prod(a, b, ntt4);
78+
auto c5 = inner_middle_prod(a, b, ntt5);
79+
vector<ull> c(c1.size(), 0);
80+
for (int i = 0; i < c.size(); i++) {
81+
ull y1 = c1[i].val();
82+
ull y2 = (c2[i].val() + M2 - y1) * I2 % M2;
83+
ull y3 = (c3[i].val() + M3 * 2 - (y1 + y2 * M1 % M3)) * I3 % M3;
84+
ull y4 = (c4[i].val() + M4 * 3 - (y1 + y2 * M1 + y3 * M12M4) % M4) * I4 % M4;
85+
ull y5 = (c5[i].val() + M5 * 4 - (y1 + y2 * M1 + y3 * M12M5 + y4 * M123M5) % M5) * I5 % M5;
86+
c[i] = y1 + y2 * M1 + y3 * M12 + y4 * M123 + y5 * M1234;
87+
}
88+
return c;
89+
}
90+
}; // namespace ConvolutionMod2_64
91+
92+
/**
93+
* @brief 畳み込み mod 2^64
94+
*/

data-structure/integer-set.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
template <class T = int, class U = unsigned long long>
44
class IntegerSet {
55
private:
6-
const static T B = 6, W = 64, MASK = W - 1;
6+
static constexpr T B = 6, W = 64, MASK = W - 1;
77
T size;
88
vector<T> start;
99
vector<U> data;

docs/fps/famous-sequences.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@
88
$$\prod_{k=1}^{\infty}(1-x^k)=\sum_{k=-\infty}^{\infty}(-1)^kx^{k(3k-1)/2}$$
99
であることを用いれば $O(N\log N)$ 時間で $p_0,p_1,\dots,p_N$ が列挙できる.
1010

11+
## ベル数
12+
13+
$n$ 元集合を空でない部分集合に分割する方法の数 $B_n$ をベル数という.
14+
指数型母関数が下のように計算できる.
15+
$$\sum_{n}\frac{B_n}{n!}x^n
16+
=\prod_{i=1}^{\infty}\sum_{j=0}^{\infty}\frac{1}{(i!)^jj!}x^{ij}
17+
=\prod_{i=1}^{\infty}\exp\left(\frac{x^i}{i!}\right)
18+
=\exp\left(\sum_{i=1}^{\infty}\frac{x^i}{i!}\right)
19+
=\exp(e^x-1)$$
20+
21+
## モンモール数
22+
23+
長さ $n$ の撹乱順列,すなわち $(1,2,\dots,n)$ の順列 $(p_1,p_2,\dots,p_n)$ で $p_i\neq i$ を満たすものの個数.
24+
25+
$a_n$ とおくと $a_n=(n-1)(a_{n-1}+a_{n-2})$ であるから $O(n)$ 時間で列挙できる.
26+
1127
## 第一種スターリング数
1228

1329
$s(n,k)$ を以下で定める.

fps/famous-sequences.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@ FormalPowerSeries<mint> PartitionFunction(int n) {
1212
return g.inv(n + 1);
1313
}
1414
template <class mint>
15+
FormalPowerSeries<mint> BellNumber(int n) {
16+
using fact = Factorial<mint>;
17+
FormalPowerSeries<mint> f(n + 1);
18+
for (int i = 1; i < f.size(); i++) f[i] = fact::fact_inv(i);
19+
f = f.exp();
20+
for (int i = 0; i < f.size(); i++) f[i] *= fact::fact(i);
21+
return f;
22+
}
23+
template <class mint>
24+
vector<mint> MontmortNumber(int n) {
25+
vector<mint> f(n + 1);
26+
f[0] = 1, f[1] = 0;
27+
for (int i = 2; i < f.size(); i++) f[i] = (i - 1) * (f[i - 1] + f[i - 2]);
28+
return f;
29+
}
30+
template <class mint>
1531
FormalPowerSeries<mint> FirstKindStirlingNumbers(int n) {
1632
FormalPowerSeries<mint> f{1};
1733
for (int l = 30; l >= 0; l--) {

fps/formal-power-series.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,10 @@ struct FormalPowerSeries : vector<mint> {
9494
}
9595
FPS operator>>=(int sz) {
9696
assert(sz >= 0);
97-
if ((int)this->size() <= sz) return {};
98-
this->erase(this->begin(), this->begin() + sz);
97+
if ((int)this->size() <= sz)
98+
this->clear();
99+
else
100+
this->erase(this->begin(), this->begin() + sz);
99101
return *this;
100102
}
101103
FPS operator>>(int sz) const {

fps/product-of-polynomials.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ FormalPowerSeries<mint> ProductOfPolynomials(vector<FormalPowerSeries<mint>> fs)
77
for (auto& f : fs) f.shrink();
88
for (auto& f : fs)
99
if (f.empty()) return {};
10-
const int B = 1 << 6;
10+
static constexpr int B = 1 << 6;
1111
for (int i = 0, j = -1; i < fs.size(); i++) {
1212
if (fs[i].size() > B) continue;
1313
if (j == -1 || fs[i].size() + fs[j].size() - 1 > B) {

fps/relaxed.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
template <class mint>
77
class RelaxedMultiply {
8-
const int B = 6;
8+
static constexpr int B = 6;
99
using fps = FormalPowerSeries<mint>;
1010
int n;
1111
fps f, g, h;
@@ -61,7 +61,7 @@ class RelaxedMultiply {
6161

6262
template <class mint>
6363
class SemiRelaxedMultiply {
64-
const int B = 6;
64+
static constexpr int B = 6;
6565
using fps = FormalPowerSeries<mint>;
6666
int n, m0;
6767
fps f, g, h;

fps/sum-of-rationals.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
template <class mint>
66
FPSRational<mint> SumOfRationals(vector<FPSRational<mint>> rs) {
7-
if (ps.empty()) return {};
7+
if (rs.empty()) return {};
88
for (auto& r : rs) {
99
r.num.shrink(), r.den.shrink();
1010
if (r.den.size() < r.num.size()) r.num.resize(r.den.size());
1111
}
12-
const int B = 1 << 5;
12+
static constexpr int B = 1 << 5;
1313
for (int i = 0, j = -1; i < rs.size(); i++) {
1414
if (rs[i].den.size() > B) continue;
1515
if (j == -1 || rs[i].den.size() + rs[j].den.size() - 1 > B) {
@@ -23,7 +23,7 @@ FPSRational<mint> SumOfRationals(vector<FPSRational<mint>> rs) {
2323
if (rs.size() == 1) return rs[0];
2424
for (auto& r : rs) {
2525
int sz = B;
26-
while (sz < r.size()) sz <<= 1;
26+
while (sz < r.num.size() || sz < r.den.size()) sz <<= 1;
2727
r.num.resize(sz);
2828
r.num.ntt();
2929
r.den.resize(sz);

math/garner-online.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ struct GarnerOnline {
99
void push(T r, T m) {
1010
T x = 0, p = 1;
1111
for (int j = 0; j < ms.size(); j++) {
12-
x = (x + y[j] * p) % ms[i];
12+
x = (x + y[j] * p) % m;
1313
p = p * ms[j] % m;
1414
}
1515
ms.push_back(m);
@@ -23,12 +23,12 @@ struct GarnerOnline {
2323
}
2424
T get() {
2525
T res = 0;
26-
for (int i = (int)ms.size() - 1; i >= 0; i--) res = res * m[i] + y[i];
26+
for (int i = (int)ms.size() - 1; i >= 0; i--) res = res * ms[i] + y[i];
2727
return res;
2828
}
2929
T get(T mod) {
3030
T res = 0;
31-
for (int i = (int)ms.size() - 1; i >= 0; i--) res = (res * m[i] + y[i]) % mod;
31+
for (int i = (int)ms.size() - 1; i >= 0; i--) res = (res * ms[i] + y[i]) % mod;
3232
return res;
3333
}
3434
};

0 commit comments

Comments
 (0)