Hello Codeforces!
Today I'll be writing about what I have learnt about combinatorics, which played, and, in my opinion, will still be playing an important role in both Codeforces and CP (short for competitive programming).
However, combinatorics is such a great subject that made that impossible for me to write it all in one blog. So, this is just the second blog, which is friendly to beginners. If you are interested, please, pay attention to this account and I'll give posts as series for a long term.
If you have found some mistakes in the text, or if you have some questions about the topic, please, leave a comment, and I'll check it weekly and reply. Also, if you find some grammar mistakes, a kind comment will be also welcomed.
Previous Blogs
Content
- Homework Tutorial
- Catalan Sequence
- Stirling Number
- Derangement
- Recurrence relation
- homework
Part 0 — Pre-knowledge
In order not to make this blog too long (it's already very long now xD), I won't explain these things anymore. You can find them on wikis or google them.
- What Combinatorics (1)(2) mentioned.
- CP basics.
- Reading simple C++ code.
Part 1 — Homework Tutorial
Task A
The first task of it can be solved with two quick powers in $$$\mathcal O(\log{(n+k)})$$$ time.
The second task can be solved with combination initiation, $$$inv[i]$$$ initiation mentioned in Task C in $$$\mathcal O(n)$$$ time.
Task B
Let's define $$$z$$$ the number of the $$$0$$$s in the array, $$$p$$$ the number of the positive elements in the array, $$$m$$$ the number of the negative elements in the array.
When the product is $$$0$$$, we have to choose at least one $$$0$$$. You may find it difficult to solve it directly, let's reduce the invalid subsets' count, which contains no $$$0$$$. So the count is $$$2^{n-z}$$$. The whole count is $$$2^n$$$, the answer is $$$2^n-2^{n-z}$$$ which can be solved in $$$\mathcal O(\log n)$$$ time.
When the product is positive, we have to choose $$$2i$$$ negative numbers. So we can enumerate the count of the negative numbers and calculate the answer. Notice that $$$2i\in[0,n]$$$. First, we can choose any subset of the set of positive numbers. So the answer is:
When the product is negative, we have to choose $$$2i+1$$$ negative numbers. So we can enumerate the count of the negative numbers and calculate the answer. Notice that $$$2i+1\in[0,n]$$$. First, we can choose any subset of the set of positive numbers. So the answer is:
All above can be solved in $$$\mathcal O(n)$$$ time.
Task C
There are two ways.
The first way: After the prework of $$$fac[]$$$ and $$$ifac[]$$$, $$$inv[i]=fac[i-1]\times ifac[i]$$$. The proof is simple: $$$\frac{(i-1)!}{i!}=\frac{1}{i}$$$.
The second way: First show you the code:
void init() {
inv[0] = inv[1] = 1;
for(int i = 2; i < N; i++) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
}
So:
Proof:
Since $$$a\bmod b=a-\lfloor\frac{a}{b}\rfloor\times b$$$, so:
Then:
Since $$$pi\equiv 0\pmod p$$$, we've got proved.
This takes $$$\mathcal O(n)$$$ time too, but less memory.
Task D
This is Catalan sequence, so let's go to the second part first and discuss it later.
Part 2 — Catalan Sequence
First Task D can be solved with dp, we define $$$f_{n}$$$ as the answer. Then:
This can be solved in $$$\mathcal O(n^2)$$$ time. But it's too slow, let's optimize it:
Proof:
Since $$$f_2=1$$$, then:
Then we let $$$f'_{n+1}=nf_{n+1}$$$
Then
So
Since $$$f'_2=f_2=1$$$
Then
Reduce of the fraction, then $$$f'_{n+1}=\dbinom{2n-2}{n-1}$$$
So
At last, $$$f_n=\dfrac{1}{n+1}\dbinom{2n}{n}$$$
This can be solved in $$$\mathcal O(2n)=\mathcal O(n)$$$ time, maybe a little bit slow.
Also we have another formula, and can be initiated in $$$\mathcal O(n)$$$ time:
Since the combination can be solved in $$$\mathcal O(n)$$$ time, and $$$\frac{1}{n+1}$$$ is exactly $$$inv[n+1]$$$ which can be initiated in $$$\mathcal O(n)$$$ time too.
This sequence $$$f$$$ is noted as Catalan sequence. Usually $$$H_n$$$ or $$$C_n$$$ denoted to it.
There are many more problems with can be solved with Catalan sequence, and it'll be put in the homework part.
Part 3 — Stirling Number
We note
Unable to parse markup [type=CF_MATHJAX]
or $$$S(n,k)$$$ as the different ways to cut $$$n$$$ different elements into $$$k$$$ undifferentiated non-empty subsets. For example, $$$S(5,3)$$$ denotes to:$\begin{matrix}[1,2,3][4][5] & [1,2][3,4][5] & [1,2][3][4,5] & [1,2][3,5][4] & [1,3][2][4,5] \ [1,3][2,4][5] & [1,3][2,5][4] & [1,4][2,3][5] & [1,4][2,5][3] & [1,4][2][3,5] \ [1,5][2,3][4] & [1,5][2,4][3] & [1,5][3,4][2] & [1,2,4][3][5] & [1,2,5][3][4] \ [1,3,4][2][5] & [1,3,5][2][4] & [1,4,5][2][3] & [1][2][3,4,5] & [1][2,3][4,5] \ [1][2,4][3,5] & [1][3][2,4,5] & [1][4][2,3,5] & [1][5][2,3,4] & [1][2,5][3,4] \end{matrix}$
So $$$S(5,3)=25$$$. Why isn't $$$[5,3][1][4,2]$$$ counted? Because it's the same as $$$[1][2,4][3,5]$$$.