diff --git a/content/4_Silver/Binary_Search.md b/content/4_Silver/Binary_Search.md index 5fb2b1f..2afff8a 100644 --- a/content/4_Silver/Binary_Search.md +++ b/content/4_Silver/Binary_Search.md @@ -2,20 +2,137 @@ id: binary-search title: "Binary Search on the Answer" author: Darren Yao + - + - Silver - Introduction to Sorting --- -## Binary Searching on the Answer +You should already be familiar with the concept of **binary searching** for a number in a sorted array. However, binary search can be extended to binary searching on the answer itself. -Oftentimes used when you need to find the minimum or maximum of some quantity such that it satisfies some property. - -### Tutorial + - - Intro to USACO 12.1 +When we binary search on the answer, we start with a search space of size $N$ which we know the answer lies in. Then, each iteration of the binary search cuts the search space in half, so the algorithm tests $O(\log N)$ values. This is efficient and much better than testing each possible value in the search space. + +Let's say we have a function `check(x)` that returns true if the answer of $x$ is possible, and false otherwise. Usually, in such problems, we'll want to find the maximum or minimum value of $x$ such that `check(x)` is true. Similarly to how binary search on an array only works on a sorted array, binary search on the answer only works if the answer function is [monotonic](https://en.wikipedia.org/wiki/Monotonic_function), meaning that it is always non-decreasing or always non-increasing. + +In particular, if we want to find the maximum `x` such that `check(x)` is true, then we can binary search if `check(x)` satisfies both of the following conditions: + + - If `check(x)` is `true`, then `check(y)` is true for all $y \leq x$. + - If `check(x)` is `false`, then `check(y)` is false for all $y \geq x$. + +In other words, we want to reduce the search space to something of the following form, using a check function as we described above. + +
true true true true true false false false false
+ +We want to find the point at which `true` becomes `false`. + +Below, we present two algorithms for binary search. The first implementation may be more intuitive, because it's closer to the binary search most students learned, while the second implementation is shorter. + +(pseudocode) + +If instead we're looking for the minimum `x` that satisfies some condition, then we can binary search if `check(x)` satisfies both of the following conditions: + + - If `check(x)` is true, then `check(y)` is true for all $y \geq x$. + - If `check(x)` is false, then `check(y)` is false for all $y \leq x$. + +The binary search function for this is very similar. Find the maximum value of $x$ such that `check(x)` is false with the algorithm above, and return $x+1$. + +## Example: [CF 577 Div. 2 C](https://codeforces.com/contest/1201/problem/C) + +Given an array `arr` of $n$ integers, where $n$ is odd, we can perform the following operation on it $k$ times: take any element of the array and increase it by $1$. We want to make the median of the array as large as possible, after $k$ operations. + +Constraints: $1 \leq n \leq 2 \cdot 10^5, 1 \leq k \leq 10^9$ and $n$ is odd. + +The solution is as follows: we first sort the array in ascending order. Then, we binary search for the maximum possible median. We know that the number of operations required to raise the median to $x$ increases monotonically as $x$ increases, so we can use binary search. For a given median value $x$, the number of operations required to raise the median to $x$ is + +$$\sum_{i=(n+1)/2}^{n} \max(0, x - \text{arr[i]}})$$ + +If this value is less than or equal to $k$, then $x$ can be the median, so our check function returns true. Otherwise, $x$ cannot be the median, so our check function returns false. + +The solution codes use the second implementation of binary search. + +Java: +```java +static int n; +static long k; +static long[] arr; +public static void main(String[] args) { + + n = r.nextInt(); k = r.nextLong(); + arr = new long[n]; + for(int i = 0; i < n; i++){ + arr[i] = r.nextLong(); + } + Arrays.sort(arr); + + pw.println(search()); + pw.close(); +} + +// binary searches for the correct answer +static long search(){ + long pos = 0; long max = (long)2E9; + for(long a = max; a >= 1; a /= 2){ + while(check(pos+a)) pos += a; + } + return pos; +} + +// checks whether the number of given operations is sufficient +// to raise the median of the array to x +static boolean check(long x){ + long operationsNeeded = 0; + for(int i = (n-1)/2; i < n; i++){ + operationsNeeded += Math.max(0, x-arr[i]); + } + if(operationsNeeded <= k){ return true; } + else{ return false; } +} +``` + +C++: + +```cpp +int n; +long long k; +vector v; + +// checks whether the number of given operations is sufficient +// to raise the median of the array to x +bool check(long long x){ + long long operationsNeeded = 0; + for(int i = (n-1)/2; i < n; i++){ + operationsNeeded += max(0, x-v[i]); + } + if(operationsNeeded <= k) return true; + else return false; +} + +// binary searches for the correct answer +long long search(){ + long long pos = 0; long long max = 2E9; + for(long long a = max; a >= 1; a /= 2){ + while(check(pos+a)) pos += a; + } + return pos; +} + +int main() { + cin >> n >> k; + for(int i = 0; i < n; i++){ + int t; + cin >> t; + v.push_back(t); + } + sort(v.begin(), v.end()); + + cout << search() << '\n'; +} +``` ### Problems - USACO - - [USACO Silver - Cow Dance](http://www.usaco.org/index.php?page=viewproblem2&cpid=690) + - [USACO Silver - Cow Dance Show](http://www.usaco.org/index.php?page=viewproblem2&cpid=690) - binary search on $K$ and simulate - [USACO Silver - Convention](http://www.usaco.org/index.php?page=viewproblem2&cpid=858) - determine whether $M$ buses suffice if every cow waits at most $T$ minutes diff --git a/content/4_Silver/Prefix_Sums.md b/content/4_Silver/Prefix_Sums.md index 0105b41..7ff7180 100644 --- a/content/4_Silver/Prefix_Sums.md +++ b/content/4_Silver/Prefix_Sums.md @@ -89,3 +89,7 @@ Which is what we were looking for! - [AtCoder Multiple of 2019](https://atcoder.jp/contests/abc164/tasks/abc164_d) - [Google Kick Start Candies](https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ff43/0000000000337b4d) (**only** Test Set 1.) + +## Additional Problems + + - [CF Edu Round 60 C: Magic Ship](https://codeforces.com/problemset/problem/1117/C) \ No newline at end of file diff --git a/content/5_Gold/DP.md b/content/5_Gold/DP.md index 3ae56c1..6152562 100644 --- a/content/5_Gold/DP.md +++ b/content/5_Gold/DP.md @@ -79,11 +79,6 @@ The following USACO problems don't fall into any of the categories below. Arrang * straightforward * [Talent Show](http://www.usaco.org/index.php?page=viewproblem2&cpid=839) * binary search + knapsack on weight - * [Cow Poetry](http://usaco.org/index.php?page=viewproblem2&cpid=897) - * First consider the case where there are only two lines with the same class. - * Requires fast modular exponentiation for full credit. - * [Exercise](http://www.usaco.org/index.php?page=viewproblem2&cpid=1043) - * With a bit of number theory * CF * [Round Subset](http://codeforces.com/contest/837/problem/D) [](59) * [Fire](http://codeforces.com/contest/864/problem/E) [](59) diff --git a/content/5_Gold/Intro_NT.md b/content/5_Gold/Intro_NT.md index 95289c6..a063fba 100644 --- a/content/5_Gold/Intro_NT.md +++ b/content/5_Gold/Intro_NT.md @@ -1,46 +1,98 @@ --- id: intro-nt title: "Introductory Number Theory" -author: Unknown +author: Darren Yao --- -
- Description: Todo -
+ - Prime Factorization + - GCD & LCM + - Modular Arithmetic -See 13 of https://www.overleaf.com/project/5e73f65cde1d010001224d8a +## Additional Resources -- Prime factorization, GCD, LCM -- Modular Arithmetic + - CSES 21.1, 21.2 + - [CF CodeNCode](https://codeforces.com/blog/entry/77137) -Also see here: https://codeforces.com/blog/entry/77137 +## Prime Factorization -# Binary Exponentiation +A number $a$ is called a **divisor** or a **factor** of a number $b$ if $b$ is divisible by $a$, which means that there exists some integer $k$ such that $b = ka$. Conventionally, $1$ and $n$ are considered divisors of $n$. A number $n > 1$ is **prime** if its only divisors are $1$ and $n$. Numbers greater than \(1\) that are not prime are **composite**. - +Every number has a unique **prime factorization**: a way of decomposing it into a product of primes, as follows: +\[ n = {p_1}^{a_1} {p_2}^{a_2} \cdots {p_k}^{a_k} \] +where the $p_i$ are distinct primes and the $a_i$ are positive integers. - - Tutorial - - CPH (23, Matrices) - - Problems - - [Currencies](https://www.hackerrank.com/contests/gs-codesprint/challenges/currencies) [](107) +Now, we will discuss how to find the prime factorization of an integer. -COWBASIC +(pseudocode) -(old) +This algorithm runs in $O(\sqrt{n})$ time, because the for loop checks divisibility for at most $\sqrt{n}$ values. Even though there is a while loop inside the for loop, dividing $n$ by $i$ quickly reduces the value of $n$, which means that the outer for loop runs less iterations, which actually speeds up the code. + +Let's look at an example of how this algorithm works, for $n = 252$. + +(table) + +At this point, the for loop terminates, because $i$ is already 3 which is greater than $\lfloor \sqrt{7} \rfloor$. In the last step, we add $7$ to the list of factors $v$, because it otherwise won't be added, for a final prime factorization of $\{2, 2, 3, 3, 7\}$. -### 4 +## GCD & LCM - * Eratosthenes' Sieve - * Tutorial - * CPH (21, NT) +The **greatest common divisor (GCD)** of two integers $a$ and $b$ is the largest integer that is a factor of both $a$ and $b$. In order to find the GCD of two numbers, we use the Euclidean Algorithm, which is as follows: -### 5 +$$\gcd(a, b) = \begin{cases} + a & b = 0 \\ + \gcd(b, a \bmod b) & b \neq 0 \\ + \end{cases}$$ - * Modular Arithmetic - * Modular Inverse - * Chinese Remainder Theorem - * Euler's Theorem, Phi Function - * Discrete Logarithm \ No newline at end of file +This algorithm is very easy to implement using a recursive function in Java, as follows: + +```java +public int gcd(int a, int b){ + if(b == 0) return a; + return gcd(b, a % b); +} +``` + +For C++, use the built-in `__gcd(a,b)`. Finding the GCD of two numbers can be done in $O(\log n)$ time, where $n = \min(a, b)$. + +The **least common multiple (LCM)** of two integers $a$ and $b$ is the smallest integer divisible by both $a$ and $b$. + +The LCM can easily be calculated from the following property with the GCD: + +$$\operatorname{lcm}(a, b) = \frac{a \cdot b}{\gcd(a, b)}$$ + +If we want to take the GCD or LCM of more than two elements, we can do so two at a time, in any order. For example, + +$$\gcd(a_1, a_2, a_3, a_4) = \gcd(a_1, \gcd(a_2, \gcd(a_3, a_4)))$$ + +## Modular Arithmetic + +In **modular arithmetic**, instead of working with integers themselves, we work with their remainders when divided by $m$. We call this taking modulo $m$. For example, if we take $m = 23$, then instead of working with $x = 247$, we use $x \bmod 23 = 17$. Usually, $m$ will be a large prime, given in the problem; the two most common values are $10^9 + 7$, and $998\,244\,353$. Modular arithmetic is used to avoid dealing with numbers that overflow built-in data types, because we can take remainders, according to the following formulas: + +$$\begin{gather*} + (a+b) \bmod m = (a \bmod m + b \bmod m) \bmod m \\ + (a-b) \bmod m = (a \bmod m - b \bmod m) \bmod m \\ + (a \cdot b) \pmod{m} = ((a \bmod m) \cdot (b \bmod m)) \bmod m \\ + a^b \bmod {m} = (a \bmod m)^b \bmod m +\end{gather*}$$ + +### Modular Exponentiation + +? + +### Modular Inverse + +Under a prime moduli, division exists. + +## Problems + + - USACO + - Both are also Knapsack DP problems. + - [Cow Poetry](http://usaco.org/index.php?page=viewproblem2&cpid=897) + - First consider the case where there are only two lines with the same class. + - Requires fast modular exponentiation for full credit. + - [Exercise](http://www.usaco.org/index.php?page=viewproblem2&cpid=1043) + - Prime factorization + - Other + - [CF VK Cup 2012 Wildcard Round 1 C](https://codeforces.com/problemset/problem/162/C) \ No newline at end of file diff --git a/content/ordering.js b/content/ordering.js index d1d0bba..3fb6498 100644 --- a/content/ordering.js +++ b/content/ordering.js @@ -49,8 +49,6 @@ const ModuleOrdering = { "dfs" ], "gold": [ - "intro-nt", - "bit", { name: "Graphs", items: [ @@ -67,6 +65,8 @@ const ModuleOrdering = { "dp-trees" ] } + "intro-nt", + "bit", ], "plat": [ "oly",