-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcombinatorics.cpp
70 lines (62 loc) · 1.89 KB
/
combinatorics.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "test_utils.hpp"
#include "algo/y_combinator.hpp"
#include "numeric/combinatorics.hpp"
#include "numeric/modnum.hpp"
using num = modnum<998244353>;
using B = Binomial<num>;
using P = Partition<num>;
using D = Permutations<num>;
auto naive_layouts(int n, int k, int a, int b) {
b = min(b, n);
return y_combinator([&](auto self, int i, int r) -> num {
if (i == k) {
return r == 0;
}
int need = (k - i - 1) * a;
num ans = 0;
for (int x = a; x <= b && r - x >= need; x++) {
ans += self(i + 1, r - x);
}
return ans;
})(0, n);
}
void stress_test_layouts() {
for (int n = 0; n <= 11; n++) {
for (int k = 0; k <= n + 1; k++) {
for (int a = 0; a <= n + 1; a++) {
assert(B::layout(n, k, a) == naive_layouts(n, k, a, n));
for (int b = a; b <= n + 1; b++) {
assert(B::bounded_layout(n, k, a, b) == naive_layouts(n, k, a, b));
}
}
}
}
}
void unit_test_combinatorics() {
B::ensure_factorial(16);
D::ensure_derangements(16);
println("factorial: {}", B::fact);
println("invfactorial: {}", B::ifact);
println("derangements: {}", D::deran);
P::ensure_partition(32);
P::ensure_partition_distinct(32);
P::ensure_partition_odd_distinct(32);
D::ensure_bell(16);
D::ensure_stir1st(16);
D::ensure_stir2nd(16);
println("partitions: {}", P::partp);
println("partitions distinct: {}", P::partq);
println("partitions odd dist: {}", P::partd);
println("bell: {}", D::belln);
for (int n = 0; n <= 16; n++) {
println("stir1st[{:2}]: {}", n, D::stir1st[n]);
}
for (int n = 0; n <= 16; n++) {
println("stir2nd[{:2}]: {}", n, D::stir2nd[n]);
}
}
int main() {
RUN_BLOCK(stress_test_layouts());
RUN_BLOCK(unit_test_combinatorics());
return 0;
}