math problems francis fok 9 th oct. content greatest common divisor prime number algorithm find...

59
Math Problems Francis Fok 9 th Oct

Upload: drusilla-warner

Post on 18-Jan-2016

223 views

Category:

Documents


1 download

TRANSCRIPT

Math Problems

Francis Fok9th Oct

Content

Greatest common divisor Prime number algorithm Find power Other forms of integer

Greatest common divisor

DefinitionDivisibility : a | b if there exists an integer x, such that a * x = b

We call a is divisor of b.

Definition

Common divisor : c is divisor of both x and y if c | x and c | y.

Greatest Common divisor: d = gcd(x,y) = Max { c | c is common divisor of

x,y)

Properties

gcd(x,y) ≥ 0 gcd(x,0) = x for x != 0 gcd(x,1) = 1 if y | x , then gcd(x,y) = y if x ≥ y > 0, then gcd(x,y) = gcd(y,x mod y) (it is known as “Euclidean algorithm”)

gcd (Recursive style)

int gcd(int x, int y){ if(x % y == 0) return y; return gcd(y, x % y);}

Assume x > 0 and y > 0 here“%” means “mod”

gcd (Iterative style)int gcd(int x,int y){ while(x % y != 0){ int t=x; x=y; y=t % y; } return y;}

Assume x > 0 and y > 0 here

lcm (least common multiple)

Lemma :If x , y ≥ 0,then x * y = gcd(x,y) * lcm(x,y)

(Algorithm)int lcm(int x, int y){ return(abs(x) * abs(y) / gcd(x,y));}

Extended Euclidean algorithm

Problem definitionGiven a pair integer x, y (all are

positive)Find a pair of integer a,b such that ax+by=gcd(x,y)

Extended Euclidean algorithmint gcd(int x, int y, int &a, int &b){ if(x mod y == 0){ a=0; b=1; return y; } int temp=a; a=b; b=temp – b * (temp div b); return gcd(y, x % y);}

Prime numberDefinition: (General accepted)Prime number = { x | x have only 2 distinct positive divisor}

Composite number = { x | x>1 and x is not prime}

Normally, 1 is neither prime nor composite.

Sometime , 1 will consider as a prime or a composite

or both.

Example

2 3 4 5 6 7 8 9 10

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30

31 32 33 34 35 36 37 38 39 40

41 42 43 44 45 46 47 48 49 50

51 52 53 54 55 56 57 58 59 60

61 62 63 64 65 66 67 68 69 70

71 72 73 74 75 76 77 78 79 80

81 82 83 84 85 86 87 88 89 90

Example

2 3 4 5 6 7 8 9 10

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30

31 32 33 34 35 36 37 38 39 40

41 42 43 44 45 46 47 48 49 50

51 52 53 54 55 56 57 58 59 60

61 62 63 64 65 66 67 68 69 70

71 72 73 74 75 76 77 78 79 80

81 82 83 84 85 86 87 88 89 90

Example

2 3 4 5 6 7 8 9 10

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30

31 32 33 34 35 36 37 38 39 40

41 42 43 44 45 46 47 48 49 50

51 52 53 54 55 56 57 58 59 60

61 62 63 64 65 66 67 68 69 70

71 72 73 74 75 76 77 78 79 80

81 82 83 84 85 86 87 88 89 90

Example

2 3 4 5 6 7 8 9 10

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30

31 32 33 34 35 36 37 38 39 40

41 42 43 44 45 46 47 48 49 50

51 52 53 54 55 56 57 58 59 60

61 62 63 64 65 66 67 68 69 70

71 72 73 74 75 76 77 78 79 80

81 82 83 84 85 86 87 88 89 90

Example

2 3 4 5 6 7 8 9 10

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30

31 32 33 34 35 36 37 38 39 40

41 42 43 44 45 46 47 48 49 50

51 52 53 54 55 56 57 58 59 60

61 62 63 64 65 66 67 68 69 70

71 72 73 74 75 76 77 78 79 80

81 82 83 84 85 86 87 88 89 90

Find Prime (Version 1)find_prime_1(int x){ array prime; //(may use vector) for(i=2 to x){ bool p=1; for(j = all index in prime) if(i%prime[j]==0) p=0; if(p) insert i into prime }}

Algorithm (Version 1)

Adv : Simple idea and simple coding space efficientDis : Time inefficient

Can we replace the “division” by “addition” and “mutliplication” only?

Find Prime (Version 2a)

find_prime_2a(int x){ bool array prime[x]; initial all prime[i]=1; prime[0]=0; prime[1]=0; for(i = 2 to x) if(prime[i]) for(int j=i*i; j<=x; j+=i) prime[j]=0;}

Find Prime (Version 2b)find_prime_2b(int x){ bool array prime[x]; initial all prime[i]=1; prime[0]=0; prime[1]=0; prime[all even except 2] = 0; for(i = 3 ; i<=sqrt(x); i+=2){ if(prime[i]) for(int j=i*i; j<=x; j+=i) prime[j]=0;}

Find Prime (Version 2b)

Adv : time efficientDis : Only return “Yes” or “No”.

Can we get the divisor from the algorithm?

Find Prime (Version 3)find_prime_3(int x){ int array prime[x]; initial all prime[i]=i; prime[0]=0; prime[1]=0; prime[all even except 2] = 2; for(i = 3 ; i<=sqrt(x); i+=2){ if(prime[i]==i) for(int j=i*i; j<=x; j+=i) if(prime[j] = j) prime[j]=i;}

Example

2 3 2 5 6 7 8 9 10

11 12 13 2 15 16 17 18 19 20

21 22 23 2 25 26 27 28 29 30

31 32 33 2 35 36 37 38 39 40

41 42 43 2 45 46 47 48 49 50

51 52 53 2 55 56 57 58 59 60

61 62 63 2 65 66 67 68 69 70

71 72 73 2 75 76 77 78 79 80

81 82 83 2 85 86 87 88 89 90

Example

2 3 2 5 2 7 2 3 2

11 2 13 2 3 2 17 2 19 2

3 2 23 2 5 2 3 2 29 2

31 2 3 2 5 2 37 2 3 2

41 2 43 2 3 2 47 2 7 2

3 2 53 2 5 2 3 2 59 2

61 2 3 2 5 2 67 2 3 2

71 2 73 2 3 2 77 2 79 2

3 2 83 2 5 2 3 2 89 2

Number theory

Definition:Relative prime x and y are relative prime iff

gcd(x,y)=1

R(x) = { y | y<x and gcd(x,y)=1}Φ(x) = | R(x) |

Formula

Φ(x) = x * product (1-1/p) where p is prime factor of x

Example : Φ(6) = 6 * (1-1/2) * (1-1/3) = 2 Φ(24) = 24 * (1-1/2) * (1-1/3) = 8

phi

phi(int x){ int sol=x,temp; while(x!=1){ temp=prime[x]; y=y*(temp-1)/temp; while(prime[x]==temp) x/=prime[x];} return sol;}

Find Power

Problem: How to find 2^n?

Algorithm(Version 1)find_power(int x){ if(x==1) return(2); return(2 * find(power(x-1));}Problem : time inefficient (linear time)What happen if we call

find_power(100000000)?

Find Power

How we get 2^100000000 by hand?(It is a DP approach)

2^1=2 2^2=4 2^4=16 2^8=256……Find the binary representation of

100000000 and multiplying with corresponding power.

Find Power (Version 2)

find_power(int x){ if(x==1) return(2) y = power(x/2) if(x mod 2==1) return(2 * y * y) else return(y * y)}

Find Power (Version 2)

Adv : sub-linear time can be improved to do any

base rather than 2

Even more powerful, the base can be a matrix.

Example8

10

11

10

11

10

111

10

21

10

11

10

11

10

112

10

41

10

21

10

21

10

114

10

81

10

41

10

41

10

118

Find

Fibonacci number

It seem nothing special using a matrix as base.

Question : Can we find the 1024th Fibonacci number in only 10 steps?

(suppose no overflowing problem)

Fibonacci number

Refer to Bryan’s presentation :Definition of Fibonacci number

f(0) = 0 f(1) = 1 f(n) = f(n – 1) + f(n – 2),

it requires 1024 steps to do.How we can only use 10 steps?

Fibonacci number

We can construct a matrix representing the recurrence relation.

Then, we can find the solution by

n

n

n

n

x

x

x

x 1

101

11

1024

1025

1024

0

1

01

11

x

x

Sum of root power

Suppose p,q are non-zero roots of x2 + bx + c = 0 where b,c are integers.

Then, how to find pn + qn for some positive integer n?

Sum of root power

Direct method :Find p and q by using the quadratic

formula and power the value up to n.

What is the problem?

Sum of root power

We know,

S = p + q = -bP = pq = c

Sum of root power

Define F(n) = pn + qn .

Then, F(n) = pn + qn

= (pn-1 + qn-1)(p+q) – (pn-2 + qn-2) pq= S F(n-1) – P F(n-2)

So,

n

n

n

n

F

F

F

FPS 1

101

Recurrence relation

In fact, we can model any recurrence relation by a matrix. And find the nth term in sub-linear time.

Improvement

If the base is a matrix , 1) Using iterative style is better

because of memory consideration.

2) Applying Jordan decomposition , we can do the multiplication even more faster. But the drawback is the decomposition is very hard.

Other forms of integer

The type “int”, “unsinged int”, “long long” have a range.

int [- 2^31 , 2^31-1]

unsigned int [ 0 , 2^32-1]

long long [- 2^63 , 2^63-1]

unsigned long long

[ 0 , 2^64-1]

Big integer

What happen if we want to store a num “12345678901234567890”?

We can use a vector to store the number.

Thus, v[0]=0, v[1]=9, v[2]=8……(Remember the order is reverse)

Make the Big Int

Make(string x){ vector<int> number; for(int i=x.size()-1; i>=0; --i) number.push_back(x[i]-’0’);}

Big Int

We need to write the addition , subtraction ,multiplicaton and division ourselves.

How to do addition?

AdditionAddition (vector<int> v, vector<int> u){ vector<int> sol; if(v.size()>u.size()){ sol=v; for(int i=0; i<u.size(); ++i) sol[i]+=u[i]; } else{ sol=u; for(int i=0; i<u.size(); ++i) sol[i]+=u[i]; } for(int i=0; i<sol.size()-1; ++i) if(sol[i]>9){ sol[i+1]+=1; sol[i]=10-sol[i]; } if(sol.back()>9){ sol.push_back(1); sol[sol.size()-2] = 10 - sol[sol.size()-2]; }}

Big Int

We can write the subtraction in the same way.

For multiplication, there are two cases,

Big-Int * Int and Big-Int * Big-Int.

MultiplicationMultiplication (vector<int> v, int u){ vector<int> sol; if(v.size()>u.size()){ sol=v; for(int i=0; i<u.size(); ++i) sol[i]*=u; } for(int i=0; i<sol.size()-1; ++i) if(sol[i]>9){ sol[i+1]+=sol[i]/10; sol[i]=sol[i] mod 10; } while(sol.back()>9){ sol.push_back(1); sol[sol.size()-2] = 10 - sol[sol.size()-2]; }}

Variation

Use string to store the big int For every cell in vector, represent

2 or more digit. (Be care the overflowing problem)

Use Double as integer

Lemma :Any real number can be represented

as Mantissa * 10^Exponentwhere 0≤Mantissa <1And Exponent is an integer

Use Double as integer

Question :How to find the last 4 digits of 2^1000?How to find the first 4 digits of 2^1000?How to find the number of digits of

2^1000?

Of course, we can use Big-int to do.But we can do it faster.

Find last 4 digits

Using the find_power and “mod”.

find_last(int x){ if(x==1) return(2) y = power(x/2) mod 10000 if(x mod 2==1) return(2 * y * y) mod 10000 else return(y * y) mod 10000}

Find first 4 digits

Use mantissa to record the solution.

find_first(int x){ mantissa=0.2; for(int i=1 to x){ mantissa *=2; if(mantissa >=1) mantissa /=10; }}

Becare :The answer = int(mantissa*10000)

Find the number of digits

Use the exponent to record the solution.find_first(int x){ mantissa=0.2; expontent = 0; for(int i=1 to x){ mantissa *=2; if(mantissa >=1) mantissa /=10; ++expontent; }}

Becare :The answer = expontent + 1

Find the number of digits

There is another way to find the number of digit by using “log”.

Number of digit = int(log 2^1000) + 1

= int(1000 log 2) + 1

Use Double as integer

Using Double is taking a risk because of precision consideration.

By the concept of numerical analysis, we can use double if we can control the error. Otherwise, using another method to do so.

Simple counting

Combination and Permutation

Use int or long long may suffer from overflow

Use double may suffer from precision

DP approach

By the identity, C(n,r) = C(n-1,r) + C(n-1,r-1)

We can find a DP + Big Int solution.

Selected ProblemGCD:10090,10104Prime:160,324,583,10139,10539,10650,10852Number theory:10090,10465,11064Find power:374,495,10655Big Int:369, 485,10118,10183,10334,10579Double as integer:474,530,701,11029