ICPCNotebooks HCMUS PenguinSpammers
ICPCNotebooks HCMUS PenguinSpammers
HCMUS-PenguinSpammers
February 3, 2022
1
HCMUS-PenguinSpammers 2
} B[0, . . .] = [1, − 21 , 16 , 0, − 30
1
, 0, 1
42
, . . .] # on k existing trees of size ni : n1 n2 · · · nk nk−2
Sums of powers: # with degrees di : (n − 2)!/((d1 − 1)! · · · (dn − 1)!)
cpx in[1 << 20]; n m Catalan numbers
X 1 X m + 1
nm = Bk · (n + 1)m+1−k ! ! !
void solve(int n) { m + 1 k=0 k
i=1 1 2n 2n 2n (2n)!
memset(d, 0, sizeof d); Cn = = − =
int t; Euler-Maclaurin formula for infinite sums: n+1 n n n+1 (n + 1)!n!
for (int i = 0; i < n; ++i) { ∞ Z ∞ ∞
X X Bk (k−1)
cin >> t; f (i) = f (x)dx − f (m) 2(2n + 1) X
d[t] = true; i=m m k=1
k! C0 = 1, Cn+1 = Cn , Cn+1 = Ci Cn−i
}
n+2
Z ∞ f (m) f 0 (m) f 000 (m)
int m; ≈ f (x)dx + − + + O(f (5) (m)) Cn = 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, . . .
cin >> m; m 2 12 720
vector<int> q(m); [noitemsep]sub-diagonal monotone paths in an n × n
Stirling numbers of the first kind
for (int i = 0; i < m; ++i) grid. strings with n pairs of parenthesis, correctly
Number of permutations on n items with k cycles.
cin >> q[i]; nested. binary trees with with n+1 leaves (0 or 2 chil-
c(n, k) = c(n − 1, k − 1) + (n − 1)c(n − 1, k), c(0, 0) = 1 dren). ordered trees with n+1 vertices. ways a convex
for (int i = 0; i < MN; ++i) { Pn k polygon with n + 2 sides can be cut into triangles by
k=0 c(n, k)x = x(x + 1) . . . (x + n − 1)
if (d[i])
in[i] = cpx(1, 0); connecting vertices with straight lines. permutations
else c(8, k) = 8, 0, 5040, 13068, 13132, 6769, 1960, 322, 28, 1 of [n] with no 3-term increasing subseq.
in[i] = cpx(0, 0); Stirling numbers of the second kind
}
Partitions of n distinct elements into exactly k groups. 2.5 Lucas Theorem
FFT(in, MN, 1);
for (int i = 0; i < MN; ++i) { S(n, k) = S(n − 1, k − 1) + kS(n − 1, k) For non-negative integers m and n and a prime p, the fol-
in[i] = in[i] * in[i]; lowing congruence relation holds: :
} S(n, 1) = S(n, n) = 1 ! !
k
FFT(in, MN, -1); k
!
m Y mi
1 X k−j k ≡ (mod p),
S(n, k) = (−1) jn n ni
int ans = 0; k! j=0 j i=0
for (int i = 0; i < q.size(); ++i) {
if (in[q[i]].real > 0.5 || d[q[i]]) { Eulerian numbers where :
ans++; Number of permutations π ∈ Sn in which exactly k el-
} m = mk pk + mk−1 pk−1 + · · · + m1 p + m0 ,
ements are greater than the previous element. k j:s s.t.
}
cout << ans << endl; π(j) > π(j + 1), k + 1 j:s s.t. π(j) ≥ j, k j:s s.t. π(j) > j. and :
}
E(n, k) = (n − k)E(n − 1, k − 1) + (k + 1)E(n − 1, k) n = nk pk + nk−1 pk−1 + · · · + n1 p + n0
int main() { are the base p expansions
of m and n respectively. This uses
E(n, 0) = E(n, n − 1) = 1
ios_base::sync_with_stdio(false);cin.tie(NULL); the convention that m n
= 0 if m ≤ n.
int n; k
!
j n+1
X
while (cin >> n) E(n, k) = (−1) (k + 1 − j)n
solve(n); j 2.6 Multinomial
j=0
return 0;
} Bell numbers
/**
Total number of partitions of n distinct elements. B(n) = * Description: Computes $\displaystyle \binom{k_1 +
1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, . . . . For p prime, \dots + k_n}{k_1, k_2, \dots, k_n} = \frac{(\sum
k_i)!}{k_1!k_2!...k_n!}$.
2.4 General purpose numbers B(pm + n) ≡ mB(n) + B(n + 1) (mod p) * Status: Tested on kattis:lexicography
*/
Bernoulli numbers Labeled unrooted trees #pragma once
EGF of Bernoulli numbers is B(t) = et −1
t
(FFT-able). # on n vertices: nn−2
HCMUS-PenguinSpammers 5
long long multinomial(vector<int>& v) { int permToInt(vector<int>& v) { for (where++; where <= n; where += where &
long long c = 1, m = v.empty() ? 1 : v[0]; int use = 0, i = 0, r = 0; -where) {
for (long long i = 1; i < v.size(); i++) { for(int x : v) r = r * ++i + t[where] += what;
for (long long j = 0; j < v[i]; j++) { __builtin_popcount(use & -(1<<x)), }
c = c * ++m / (j + 1); use |= 1 << x; // (note: }
} minus, not ~!)
} return r; void add(int from, int to, long long what) {
return c; } add(from, what);
} add(to + 1, -what);
}
int sum(int seg, int l, int r, int a, int b){ const int MN = 26; // size of alphabet struct line{
if(l > b || r < a) return 0; const int MS = 100010; // Number of states. long a, b;
if(l >= a && r <= b) return node[seg]; line() {};
int mid = (l + r)/2; struct trie{ line(long a, long b) : a(a), b(b) {};
return sum(2*seg + 1, l, mid, a, b) + sum(2*seg + struct node{ bool operator < (const line &A) const {
2, mid + 1, r, a, b); int c; return pll(a,b) < pll(A.a,A.b);
} int a[MN]; }
}; };