Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
Mathematics in OI Prepared by Ivan Li
Mathematics in OI • Greatest Common Divisor • Finding Primes • High Precision Arithmetic • Partial Sum and Differencing
Greatest Common Divisor • Motivation • Sometimes we want “k divides m” and “k divides n” occur simultaneously. • And we want to merge the two statements into one equivalent statement: “k divides ?”
Greatest Common Divisor • Definition • The greatest natural number dividing both n and m • A natural number k dividing both n and m, such that for each natural number h dividing both n and m, we have k divisible by h.
Greatest Common Divisor • How to find it? • Check each natural number not greater than m and n if it divides both m and n. Then select the greatest one. • Euclidean Algorithm
Euclidean Algorithm • Assume m > n GCD(m,n) While n > 0 m = m mod n swap m and n Return m
Greatest Common Divisor • What if we want the greatest number which divides n1,n2, …, nm-1 and nm? • Apply GCD two-by-two • gcd(n1,n2, …,nm) = gcd(n1,gcd(n2,gcd(n3,…gcd(nm-1,nm)…))
Applications • Solve mx + ny = a for integers x and y • Can be solved if and only if a is divisible by gcd(m,n)
Applications • Simplifying a fraction m/n • If gcd(m,n) > 1, then the fraction can be simplified by dividing gcd(m,n) on the numerator and the denominator.
Least Common Multiple • Definition • The least natural number divisible by both n and m • A natural number k divisible by both n and m, such that for each natural number h divisible by both n and m, we have k divides h. • Formula • lcm(m,n) = mn/gcd(m,n)
Least Common Multiple • What if we want to find the LCM of more than two numbers? • Apply LCM two-by-two?
Definition of Prime Numbers An integer p greater than 1 such that: • p has factors 1 and p only? • If p = ab, a b, then a = 1 and b = p ? • If p divides ab, then p divides a or p divides b ? • p divides (p - 1)! + 1 ?
Test for a prime number • By Property 1 • For each integer greater than 1 and less than p, check if it divides p • Actually we need only to check integers not greater than sqrt(p) (Why?)
Finding Prime Numbers • For each integer, check if it is a prime • Prime List • Sieve of Eratosthenes
Prime List • Stores a list of prime numbers found • For each integer, check if it is divisible by any of the prime numbers found • If not, then it is a prime. Add it to the list.
Sieve of Eratosthenes • Stores an array of Boolean values Comp[i] which indicates whether i is a known composite number
Sieve of Eratosthenes for i = 2 … n If not Comp[i] output i j = 2*i while j n Comp[j] = true j = j + i
Optimization • Consider odd numbers only • Do not forget to add 2, the only even prime
High Precision Arithmetic • 32-bit signed integer:-2147483648 … 2147483647 • 64-bit signed integer:-9223372036854775808 … 9223372036854775807 • How to store a 100 digit number?
High Precision Arithmetic • Use an array to store the digits of the number • Operations: • Comparison • Addition / Subtraction • Multiplication • Division and remainder
High Precision Division • Locate the position of the first digit of the quotient • For each digit of the quotient (starting from the first digit), find its value by binary search.
High Precision Arithmetic • How to select the base? • Power of 2 : Saves memory • Power of 10 : Easier input / output • 1000 or 10000 for 16-bit integer array • Beware of carry
More on HPA • How to store • negative numbers? • fractions? • floating-point numbers?
Partial Sum • Motivation • How to find the sum of the 3rd to the 6th element of an array a[i] ? • a + a + a + a • How to find the sum of the 1000th to the 10000th element? • A for-loop will take much time • In order to find the sum of a range in an array efficiently, we need to do some preprocessing.
Partial Sum • Use an array s[i] to store the sum of the first i elements. • s[i] = a + a + … + a[i] • The sum of the j th element to the k th element = s[k] – s[j-1] • We usually set s = 0
Partial Sum • How to compute s[i] ? • During input s = 0 for i = 1 to n input a[i] s[i] = s[i-1] + a[i]
Differencing • Motivation • How to increment the 3rd to the 6th element of an array a[i] ? • a++, a++, a++, a++ • How to increment the 1000th to the 10000th element? • A for-loop will take much time • In order to increment(or add an arbitrary value to) a range of elements in an array efficiently, we will use a special method to store the array.
Differencing • Use an array d[i] to store the difference between a[i] and a[i-1]. • d[i] = a[i] - a[i-1] • When the the j th element to the k th element is incremented, • d[j] ++, d[k+1] - - • We usually set d = a
Differencing • Easy to compute d[i] • But how to convert it back to a[i]? • Before (or during) output a = 0 for i = 1 to n a[i] = a[i-1] + d[i] output a[i] • Quite similar to partial sum, isn’t it?
Relation between the two methods • They are “inverse” of each other • Denote the partial sum of a by a • Denote the difference of a by a • The difference operator • We have (a) = (a) = a
Comparison • Partial sum - Fast sum of range query • Difference - Fast range incrementation • Ordinary array - Fast query and incrementation on single element
Does there exist a method to perform range query and range update in constant time?