Skip to content

Commit 4eae2f8

Browse files
authored
Merge branch 'cp-algorithms:master' into typo
2 parents eac2bb3 + 0f2453d commit 4eae2f8

58 files changed

Lines changed: 866 additions & 90 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[![Translation Progress](https://img.shields.io/badge/translation_progress-85.2%25-yellowgreen.svg)](https://github.com/cp-algorithms/cp-algorithms/wiki/Translation-Progress)
88

99
The goal of this project is to translate the wonderful resource
10-
[http://e-maxx.ru/algo](http://e-maxx.ru/algo) which provides descriptions of many algorithms
10+
[https://e-maxx.ru/algo](https://e-maxx.ru/algo) which provides descriptions of many algorithms
1111
and data structures especially popular in field of competitive programming.
1212
Moreover we want to improve the collected knowledge by extending the articles
1313
and adding new articles to the collection.
@@ -16,6 +16,7 @@ Compiled pages are published at [https://cp-algorithms.com/](https://cp-algorith
1616

1717
## Changelog
1818

19+
- June 26, 2023: Added automatic RSS feeds for [new articles](https://cp-algorithms.com/feed_rss_created.xml) and [updates in articles](https://cp-algorithms.com/feed_rss_updated.xml).
1920
- December 20, 2022: The repository name and the owning organizations were renamed! Now the repo is located at [https://github.com/cp-algorithms/cp-algorithms](https://github.com/cp-algorithms/cp-algorithms). It is recommended to update the upstream link in your local repositories, if you have any.
2021
- October 31, 2022: It is now possible to select and copy $\LaTeX$ source code of formulas within the articles.
2122
- June 8, 2022: Tags are enabled. Each article is now marked whether it is translated or original, overall tag info is present in the [tag index](https://cp-algorithms.com/tags.html). For translated articles, clicking on `From: X` tag would lead to the original article.
@@ -25,6 +26,8 @@ Compiled pages are published at [https://cp-algorithms.com/](https://cp-algorith
2526

2627
### New articles
2728

29+
- (10 September 2023) [Tortoise and Hare Algorithm](https://cp-algorithms.com/others/tortoise_and_hare.html)
30+
- (12 July 2023) [Finding faces of a planar graph](https://cp-algorithms.com/geometry/planar.html)
2831
- (18 April 2023) [Bit manipulation](https://cp-algorithms.com/algebra/bit-manipulation.html)
2932
- (17 October 2022) [Binary Search](https://cp-algorithms.com/num_methods/binary_search.html)
3033
- (17 October 2022) [MEX (Minimum Excluded element in an array)](https://cp-algorithms.com/sequences/mex.html)

mkdocs.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
site_name: Algorithms for Competitive Programming
2+
site_url: https://cp-algorithms.com
3+
site_description: 'The goal of this project is to translate the wonderful resource http://e-maxx.ru/algo which provides descriptions of many algorithms and data structures especially popular in field of competitive programming. Moreover we want to improve the collected knowledge by extending the articles and adding new articles to the collection.'
24
docs_dir: src
35
site_dir: public
46
use_directory_urls: false
@@ -20,17 +22,17 @@ theme:
2022
icon:
2123
repo: fontawesome/brands/github
2224
features:
23-
- navigation.tracking
2425
- navigation.tabs
2526
- toc.integrate
2627
- search.suggest
2728
repo_url: https://github.com/cp-algorithms/cp-algorithms
29+
repo_name: cp-algorithms/cp-algorithms
2830
edit_uri: edit/master/src/
2931
copyright: Text is available under the <a href="https://github.com/cp-algorithms/cp-algorithms/blob/master/LICENSE">Creative Commons Attribution Share Alike 4.0 International</a> License<br/>Copyright &copy; 2014 - 2022 by <a href="https://github.com/cp-algorithms">https://github.com/cp-algorithms</a>
3032
extra_javascript:
3133
- javascript/config.js
3234
- https://polyfill.io/v3/polyfill.min.js?features=es6
33-
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
35+
- https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js
3436
extra_css:
3537
- stylesheets/extra.css
3638

@@ -50,6 +52,8 @@ markdown_extensions:
5052
emoji_index: !!python/name:materialx.emoji.twemoji
5153
emoji_generator: !!python/name:materialx.emoji.to_svg
5254
- meta
55+
- toc:
56+
permalink: true
5357

5458
plugins:
5559
- mkdocs-simple-hooks:
@@ -70,6 +74,7 @@ plugins:
7074
token: !ENV MKDOCS_GIT_COMMITTERS_APIKEY
7175
enabled: !ENV [MKDOCS_ENABLE_GIT_COMMITTERS, False]
7276
- macros
77+
- rss
7378

7479
extra:
7580
analytics:

scripts/install-mkdocs.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ pip install \
77
mkdocs-git-authors-plugin \
88
mkdocs-git-revision-date-localized-plugin \
99
mkdocs-simple-hooks \
10+
mkdocs-rss-plugin \
1011
plugins/mkdocs-git-committers-plugin-2

src/algebra/binary-exp.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,13 @@ vector<int> applyPermutation(vector<int> sequence, vector<int> permutation) {
144144
return newSequence;
145145
}
146146
147-
vector<int> permute(vector<int> sequence, vector<int> permutation, long long b) {
148-
while (b > 0) {
149-
if (b & 1) {
147+
vector<int> permute(vector<int> sequence, vector<int> permutation, long long k) {
148+
while (k > 0) {
149+
if (k & 1) {
150150
sequence = applyPermutation(sequence, permutation);
151151
}
152152
permutation = applyPermutation(permutation, permutation);
153-
b >>= 1;
153+
k >>= 1;
154154
}
155155
return sequence;
156156
}
@@ -253,9 +253,15 @@ $$a \cdot b = \begin{cases}
253253
* [UVa 374 - Big Mod](http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=310)
254254
* [UVa 11029 - Leading and Trailing](https://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1970)
255255
* [Codeforces - Parking Lot](http://codeforces.com/problemset/problem/630/I)
256+
* [leetcode - Count good numbers](https://leetcode.com/problems/count-good-numbers/)
257+
* [Codechef - Chef and Riffles](https://www.codechef.com/JAN221B/problems/RIFFLES)
258+
* [Codeforces - Decoding Genome](https://codeforces.com/contest/222/problem/E)
259+
* [Codeforces - Neural Network Country](https://codeforces.com/contest/852/problem/B)
260+
* [Codeforces - Magic Gems](https://codeforces.com/problemset/problem/1117/D)
256261
* [SPOJ - The last digit](http://www.spoj.com/problems/LASTDIG/)
257262
* [SPOJ - Locker](http://www.spoj.com/problems/LOCKER/)
258263
* [LA - 3722 Jewel-eating Monsters](https://vjudge.net/problem/UVALive-3722)
259264
* [SPOJ - Just add it](http://www.spoj.com/problems/ZSUM/)
260-
* [Codechef - Chef and Riffles](https://www.codechef.com/JAN221B/problems/RIFFLES)
261-
* [leetcode - Count good numbers](https://leetcode.com/problems/count-good-numbers/)
265+
* [Codeforces - Stairs and Lines](https://codeforces.com/contest/498/problem/E)
266+
267+

src/algebra/bit-manipulation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ $1 \ll x$ is a number with only the $x$-th bit set, while $\sim(1 \ll x)$ is a n
116116

117117
### Check if a bit is set
118118

119-
The value of the $x$-th bit can be by shifting the number $x$ positions to the right, the $x$-th bit is the units place, therefore we can extract it by performing a bitwise & with 1
119+
The value of the $x$-th bit can be checked by shifting the number $x$ positions to the right, so that the $x$-th bit is at the unit place, after which we can extract it by performing a bitwise & with 1.
120120

121121
``` cpp
122122
bool is_set(unsigned int number, int x) {
@@ -170,7 +170,7 @@ int countSetBits(int n)
170170
}
171171
```
172172
173-
### Addtional tricks
173+
### Additional tricks
174174
175175
- $n ~\&~ (n + 1)$ clears all trailing ones: $0011~0111_2 \rightarrow 0011~0000_2$.
176176
- $n ~|~ (n + 1)$ sets the last cleared bit: $0011~0101_2 \rightarrow 0011~0111_2$.

src/algebra/discrete-log.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ This problem can be solved using the meet-in-the-middle method as follows:
4747

4848
## Complexity
4949

50-
We can calculate $f_1(p)$ in $O(\log m)$ using the [binary exponentation algorithm](binary-exp.md). Similarly for $f_2(q)$.
50+
We can calculate $f_1(p)$ in $O(\log m)$ using the [binary exponentiation algorithm](binary-exp.md). Similarly for $f_2(q)$.
5151

5252
In the first step of the algorithm, we need to calculate $f_1$ for every possible argument $p$ and then sort the values. Thus, this step has complexity:
5353

@@ -107,7 +107,7 @@ Internally, `map` uses a red-black tree to store values.
107107
Thus this code is a little bit slower than if we had used an array and binary searched, but is much easier to write.
108108
109109
Notice that our code assumes $0^0 = 1$, i.e. the code will compute $0$ as solution for the equation $0^x \equiv 1 \pmod m$ and also as solution for $0^x \equiv 0 \pmod 1$.
110-
This is an often used convention in algebra, but it's also not univerally accepted in all areas.
110+
This is an often used convention in algebra, but it's also not universally accepted in all areas.
111111
Sometimes $0^0$ is simply undefined.
112112
If you don't like our convention, then you need to handle the case $a=0$ separately:
113113

src/algebra/divisors.md

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ A way of thinking about it is the following:
2929
* If there are two distinct prime divisors $n = p_1^{e_1} \cdot p_2^{e_2}$, then you can arrange all divisors in form of a tabular.
3030

3131
$$\begin{array}{c|ccccc}
32-
& 1 & p_2 & p_2^2 & \dots & p_2^{e_2} \\\\
33-
\hline
32+
& 1 & p_2 & p_2^2 & \dots & p_2^{e_2} \\\\\hline
3433
1 & 1 & p_2 & p_2^2 & \dots & p_2^{e_2} \\\\
3534
p_1 & p_1 & p_1 \cdot p_2 & p_1 \cdot p_2^2 & \dots & p_1 \cdot p_2^{e_2} \\\\
3635
p_1^2 & p_1^2 & p_1^2 \cdot p_2 & p_1^2 \cdot p_2^2 & \dots & p_1^2 \cdot p_2^{e_2} \\\\
@@ -42,18 +41,39 @@ So the number of divisors is trivially $(e_1 + 1) \cdot (e_2 + 1)$.
4241

4342
* A similar argument can be made if there are more then two distinct prime factors.
4443

44+
45+
```cpp
46+
long long numberOfDivisors(long long num) {
47+
long long total = 1;
48+
for (int i = 2; (long long)i * i <= num; i++) {
49+
if (num % i == 0) {
50+
int e = 0;
51+
do {
52+
e++;
53+
num /= i;
54+
} while (num % i == 0);
55+
total *= e + 1;
56+
}
57+
}
58+
if (num > 1) {
59+
total *= 2;
60+
}
61+
return total;
62+
}
63+
```
64+
4565
## Sum of divisors
4666
4767
We can use the same argument of the previous section.
4868
4969
* If there is only one distinct prime divisor $n = p_1^{e_1}$, then the sum is:
50-
70+
5171
$$1 + p_1 + p_1^2 + \dots + p_1^{e_1} = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1}$$
5272
5373
* If there are two distinct prime divisors $n = p_1^{e_1} \cdot p_2^{e_2}$, then we can make the same table as before.
5474
The only difference is that now we now want to compute the sum instead of counting the elements.
5575
It is easy to see, that the sum of each combination can be expressed as:
56-
76+
5777
$$\left(1 + p_1 + p_1^2 + \dots + p_1^{e_1}\right) \cdot \left(1 + p_2 + p_2^2 + \dots + p_2^{e_2}\right)$$
5878
5979
$$ = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1}$$
@@ -62,6 +82,33 @@ $$ = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1}$$
6282
6383
$$\sigma(n) = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1} \cdots \frac{p_k^{e_k + 1} - 1}{p_k - 1}$$
6484
85+
```cpp
86+
long long SumOfDivisors(long long num) {
87+
long long total = 1;
88+
89+
for (int i = 2; (long long)i * i <= num; i++) {
90+
if (num % i == 0) {
91+
int e = 0;
92+
do {
93+
e++;
94+
num /= i;
95+
} while (num % i == 0);
96+
97+
long long sum = 0, pow = 1;
98+
do {
99+
sum += pow;
100+
pow *= i;
101+
} while (e-- > 0);
102+
total *= sum;
103+
}
104+
}
105+
if (num > 1) {
106+
total *= (1 + num);
107+
}
108+
return total;
109+
}
110+
```
111+
65112
## Multiplicative functions
66113

67114
A multiplicative function is a function $f(x)$ which satisfies

src/algebra/factorization.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ In each iteration the first pointer advances to the next element, but the second
271271
It's not hard to see, that if there exists a cycle, the second pointer will make at least one full cycle and then meet the first pointer during the next few cycle loops.
272272
If the cycle length is $\lambda$ and the $\mu$ is the first index at which the cycle starts, then the algorithm will run in $O(\lambda + \mu)$ time.
273273

274-
This algorithm is also known as **tortoise and the hare algorithm**, based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race.
274+
This algorithm is also known as the [Tortoise and Hare algorithm](../others/tortoise_and_hare.md), based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race.
275275

276276
It is actually possible to determine the parameter $\lambda$ and $\mu$ using this algorithm (also in $O(\lambda + \mu)$ time and $O(1)$ space), but here is just the simplified version for finding the cycle at all.
277277
The algorithm and returns true as soon as it detects a cycle.

src/algebra/garners-algorithm.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ A mixed radix representation is a positional numeral system, that's a generaliza
1919
For instance the decimal numeral system is a positional numeral system with the radix (or base) 10.
2020
Every a number is represented as a string of digits $d_1 d_2 d_3 \dots d_n$ between $0$ and $9$, and
2121
E.g. the string $415$ represents the number $4 \cdot 10^2 + 1 \cdot 10^1 + 5 \cdot 10^0$.
22-
In general the string of digits $d_1 d_2 d_3 \dots d_n$ represents the number $d_1 b^{n-1} + d_2 b^{n-2} + \cdots + d_n b^0$ in the positional numberal system with radix $b$.
22+
In general the string of digits $d_1 d_2 d_3 \dots d_n$ represents the number $d_1 b^{n-1} + d_2 b^{n-2} + \cdots + d_n b^0$ in the positional numeral system with radix $b$.
2323

2424
In a mixed radix system, we don't have one radix any more. The base varies from position to position.
2525

src/algebra/module-inverse.md

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ $$a \cdot x \equiv 1 \mod m.$$
1616
We will also denote $x$ simply with $a^{-1}$.
1717

1818
We should note that the modular inverse does not always exist. For example, let $m = 4$, $a = 2$.
19-
By checking all possible values modulo $m$ is should become clear that we cannot find $a^{-1}$ satisfying the above equation.
19+
By checking all possible values modulo $m$, it should become clear that we cannot find $a^{-1}$ satisfying the above equation.
2020
It can be proven that the modular inverse exists if and only if $a$ and $m$ are relatively prime (i.e. $\gcd(a, m) = 1$).
2121

2222
In this article, we present two methods for finding the modular inverse in case it exists, and one method for finding the modular inverse for all numbers in linear time.
@@ -77,32 +77,37 @@ From these results, we can easily find the modular inverse using the [binary exp
7777

7878
Even though this method is easier to understand than the method described in previous paragraph, in the case when $m$ is not a prime number, we need to calculate Euler phi function, which involves factorization of $m$, which might be very hard. If the prime factorization of $m$ is known, then the complexity of this method is $O(\log m)$.
7979

80-
## Finding the modular inverse using Euclidean Division
80+
<div id="finding-the-modular-inverse-using-euclidean-division"></div>
81+
## Finding the modular inverse for prime moduli using Euclidean Division
8182

82-
Given that $m > i$ (or we can modulo to make it smaller in 1 step), according to [Euclidean Division](https://en.wikipedia.org/wiki/Euclidean_division)
83+
Given a prime modulus $m > a$ (or we can apply modulo to make it smaller in 1 step), according to [Euclidean Division](https://en.wikipedia.org/wiki/Euclidean_division)
8384

84-
$$m = k \cdot i + r$$
85+
$$m = k \cdot a + r$$
8586

86-
where $k = \left\lfloor \frac{m}{i} \right\rfloor$ and $r = m \bmod i$, then
87+
where $k = \left\lfloor \frac{m}{a} \right\rfloor$ and $r = m \bmod a$, then
8788

8889
$$
8990
\begin{align*}
90-
& \implies & 0 & \equiv k \cdot i + r & \mod m \\
91-
& \iff & r & \equiv -k \cdot i & \mod m \\
92-
& \iff & r \cdot i^{-1} & \equiv -k & \mod m \\
93-
& \iff & i^{-1} & \equiv -k \cdot r^{-1} & \mod m
91+
& \implies & 0 & \equiv k \cdot a + r & \mod m \\
92+
& \iff & r & \equiv -k \cdot a & \mod m \\
93+
& \iff & r \cdot a^{-1} & \equiv -k & \mod m \\
94+
& \iff & a^{-1} & \equiv -k \cdot r^{-1} & \mod m
9495
\end{align*}
9596
$$
9697

97-
From there we can have the following recursive function (in C++) for computing the modular inverse for number $i$ with respect to module $m$
98+
Note that this reasoning does not hold if $m$ is not prime, since the existence of $a^{-1}$ does not imply the existence of $r^{-1}$
99+
in the general case. To see this, lets try to calculate $5^{-1}$ modulo $12$ with the above formula. We would like to arrive at $5$,
100+
since $5 \cdot 5 \equiv 1 \bmod 12$. However, $12 = 2 \cdot 5 + 2$, and we have $k=2$ and $r=2$, with $2$ being not invertible modulo $12$.
101+
102+
If the modulus is prime however, all $a$ with $0 < a < m$ are invertible modulo $m$, and we can have the following recursive function (in C++) for computing the modular inverse for number $a$ with respect to $m$
98103

99104
```{.cpp file=modular_inverse_euclidean_division}
100-
int inv(int i) {
101-
return i <= 1 ? i : m - (long long)(m/i) * inv(m % i) % m;
105+
int inv(int a) {
106+
return a <= 1 ? a : m - (long long)(m/a) * inv(m % a) % m;
102107
}
103108
```
104109
105-
The exact time complexity of the this recursion is not known. It's is somewhere between $O(\frac{\log m}{\log\log m})$ and $O(n^{\frac{1}{3} - \frac{2}{177} + \epsilon})$.
110+
The exact time complexity of the this recursion is not known. It's is somewhere between $O(\frac{\log m}{\log\log m})$ and $O(m^{\frac{1}{3} - \frac{2}{177} + \epsilon})$.
106111
See [On the length of Pierce expansions](https://arxiv.org/abs/2211.08374).
107112
In practice this implementation is fast, e.g. for the modulus $10^9 + 7$ it will always finish in less than 50 iterations.
108113
@@ -111,8 +116,8 @@ Applying this formula, we can also precompute the modular inverse for every numb
111116
112117
```{.cpp file=modular_inverse_euclidean_division_all}
113118
inv[1] = 1;
114-
for(int i = 2; i < m; ++i)
115-
inv[i] = m - (long long)(m/i) * inv[m%i] % m;
119+
for(int a = 2; a < m; ++a)
120+
inv[a] = m - (long long)(m/a) * inv[m%a] % m;
116121
```
117122

118123
## Finding the modular inverse for array of numbers modulo $m$

0 commit comments

Comments
 (0)