I am reading an algorithms textbook and I am stumped by this question:
Suppose we want to compute the value x^y, where x and y are positive
integers with m and n bits, respectively. One way to solve the problem is to perform y - 1 multiplications by x. Can you give a more efficient algorithm that uses only O(n) multiplication steps?
Would this be a divide and conquer algorithm? y-1 multiplications by x would run in theta(n) right? .. I don't know where to start with this question
I understand this better in an iterative way:
You can compute x^z for all powers of two: z = (2^0, 2^1, 2^2, ... ,2^(n-1))
Simply by going from 1 to n and applying x^(2^(i+1)) = x^(2^i) * x^(2^i).
Now you can use these n values to compute x^y:
result = 1
for i=0 to n-1:
if the i'th bit in y is on:
result *= x^(2^i)
return result
All is done in O(n)
Apply a simple recursion for divide and conquer.
Here i am posting a more like a pseudo code.
x^y :=
base case: if y==1 return x;
if y%2==0:
then (x^2)^(y/2;
else
x.(x^2)^((y-1)/2);
The y-1 multiplications solution is based on the identity x^y = x * x^(y-1). By repeated application of the identity, you know that you will decrease y down to 1 in y-1 steps.
A better idea is to decrease y more "energically". Assuming an even y, we have x^y = x^(2*y/2) = (x^2)^(y/2). Assuming an odd y, we have x^y = x^(2*y/2+1) = x * (x^2)^(y/2).
You see that you can halve y, provided you continue the power computation with x^2 instead of x.
Recursively:
Power(x, y)=
1 if y = 0
x if y = 1
Power(x * x, y / 2) if y even
x * Power(x * x, y / 2) if y odd
Another way to view it is to read y as a sum of weighted bits. y = b0 + 2.b1 + 4.b2 + 8.b3...
The properties of exponentiation imply:
x^y = x^b0 . x^(2.b1) . x^(4.b2) . x^(8.b2)...
= x^b0 . (x^2)^b1 . (x^4)^b2 . (x^8)^b3...
You can obtain the desired powers of x by squaring, and the binary decomposition of y tells you which powers to multiply.
Related
I do understand the algorithm but can't find a way to define its complexity, the only thing i know is it have something to with the second parameter, because if it was smaller the steps will be fewer. Do you have any idea how can i do this? and is there any general way to define time complexity for any given algorithm?
egyptian multiplication algorithm:
def egMul(x, y):
res = 0
while(y>0):
if(y%2==0):
x = x * 2
y = y / 2
else:
y = y - 1
res = res + x
return res
This code performs Theta(log(y)) arithmetic operations. By considering the binary representation of y, you can see it performs the else branch for each 1 that appears in the binary representation, and it performs the first branch of the if (the one that divides y by 2) floor(log_2(y)) times.
The task is to find the amount of distinct pairs of {x, y} that fits the equation 1/x + 1/y = 1/n, with n being the input given by the user. Different ordering of x and y does not count as a new pair.
For example, the value n = 2 will mean 1/n = 1/2. 1/2 can be formed with two pairs of {x, y}, whcih are 6 and 3 and 4 and 4.
The value n = 3 will mean 1/n = 1/3. 1/3 can be formed with two pairs of {x, y}, which are 4 and 12 and 6 and 6.
The mathematical equation of 1/x + 1/y = 1/n can be converted to y = nx/(x-n) where if y and x in said converted equation are whole, they count as a pair of {x, y}. Using said converted formula, I will iterate n times starting from x = n + 1 and adding x by 1 per iteration to find whether nx % (x - n) == 0; if it yields true, the x and y are a new distinct pair.
I found the answer to limit my iteration by n times by manually computing the answers and finding the number of repetitions 'pattern'. x also starts with n+1 because otherwise, division by zero will happen or y will result in a negative number. The modulo operator is to indicate that the y attained is whole.
Questions:
Is there a mathematical explanation behind why the iteration is limited to n times? I found out that the limit of iteration is n times by doing manual computation and finding the pattern: that I only need to iterate n times to find the amount of distinct pairs.
Is there another way to find the amount of distinct pairs {x, y} other than my method above, which is by finding the VALUES of distinct pairs itself and then summing the amount of distinct pair? Is there a quick mathematical formula I'm not aware of?
For reference, my code can be seen here: https://gist.github.com/TakeNoteIAmHere/596eaa2ccf5815fe9bbc20172dce7a63
Assuming that x,y,n > 0 we have
Observation 1: both, x and y must be greater than n
Observation 2: since (x,y) and (y,x) do not count as distinct, we can assume that x <= y.
Observation 3: x = y = 2n is always a solution and if x > 2n then y < x (thus no new solution)
This means the possible values for x are from n+1 up to 2n.
A little algebra convers the equation
1/x + 1/y = n
into
(x-n)*(y-n) = n*n
Since we want a solution in integers, we seek integers f, g so that
f*g = n*n
and then the solution for x and y is
x = f+n, y = g+n
I think the easiest way to proceed is to factorise n, ie write
n = (P[1]^k[1]) * .. *(P[m]^k[m])
where the Ps are distinct primes, the ks positive integers and ^ denotes exponentiation.
Then the possibilities for f and g are
f = P[1]^a[1]) * .. *(P[m]^a[m])
g = P[1]^b[1]) * .. *(P[m]^b[m])
where the as and bs satisfy, for each i=1..m
0<=a[i]<=2*k[i]
b[i] = 2*k[i] - a[i]
If we just wanted to count the number of solutions, we would just need to count the number of fs, ie the number of distinct sequences a[]. But this is just
Nall = (2*k[1]+1)*... (2*[k[m]+1)
However we want to count the solution (f,g) and (g,f) as being the same. There is only one case where f = g (because the factorisation into primes is unique, we can only have f=g if the a[] equal the b[]) and so the number we seek is
1 + (Nall-1)/2
I need to derive an algorithm in C++ to calculate integer powers m^n that uses the loop invariant r = y^n and the loop condition y != m.
I tried using the instruction y= y+1 to advance, but I don´t know how to obtain (y+1)^n from y^n, and it shouldn't be difficult to find . So, probably, this isn't the correct path to follow
Could you help me to derive the program?
EDIT: this is a problem from the subject Data Structures and Algorithms. The difficulty ( if there is at all) shouldn't be mathematic.
EDIT2: Just to clarify, the difficulty of the problem is using the invariant y^n and loop condition y != m. If I vary the n I'm not achieving that
Given w and P such that 2^w > m, P > 2^(wn), and 2^((P-1)/2) = -1 mod P,
then 2 is a generator mod P, and there will be some x such that 2^x = m mod P, so:
if (m<=1 || n==1)
return m;
if (n==0)
return 1;
let y = 2;
let r = 1<<n;
while(y!=m)
{
y = (y*2)%P;
r = (r*(1<<n))%P;
}
return r;
Unless your function needs to produce bignum results, you can just pick the largest P that fits into an integer in your language.
There is no useful relation between (y+1)^n and y^n (you can write (y+1)^n = (√(y^n)+1)^n or (y+1)^n = (1+1/y)^n y^n, but this leads you nowhere).
If y was factored, you could exploit (a.b)^n = (a^n).(b^n), but you would need a table of the nth powers of the primes.
I can't see an answer that makes sense.
You can also think of the Binomial theorem,
(y+1)^n = y^n + n y^(n-1) + n(n-1)/2 y^(n-2) + ... 1
but this is worse than anything: you need to compute n binomial coefficients, and update all powers of y from 0 to n. The total cost of the computation would be ridiculously high.
I'm trying to implement Pollard Rho based on pseudocode I found on Wikipedia, but it doesn't appear to work for the numbers 4, 8, and 25, and I have no clue why.
Here's my code:
long long x = initXY;
long long y = initXY;
long long d = 1;
while (d == 1) {
x = polynomialModN(x, n);
y = polynomialModN(polynomialModN(y, n), n);
d = gcd(labs(x - y), n);
}
if (d == n)
return getFactor(n, initXY + 1);
return d;
This is my polynomial function:
long long polynomialModN(long long x, long long n) {
return (x * x + 1) % n;
}
And this is example pseudocode from Wikipedia:
x ← 2; y ← 2; d ← 1
while d = 1:
x ← g(x)
y ← g(g(y))
d ← gcd(|x - y|, n)
if d = n:
return failure
else:
return d
Only difference: I don't return failure but instead try different initializing variables, as Wikipedia also notes this:
Here x and y corresponds to x i {\displaystyle x_{i}} x_{i} and x j
{\displaystyle x_{j}} x_{j} in the section about core idea. Note that
this algorithm may fail to find a nontrivial factor even when n is
composite. In that case, the method can be tried again, using a
starting value other than 2 or a different g ( x ) {\displaystyle
g(x)} g(x).
Does Pollard-Rho just not work for certain numbers? What are their characteristics? Or am I doing something wrong?
Pollard Rho does not work on even numbers. If you have an even number, first remove all factors of 2 before applying Pollard Rho to find the odd factors.
Pollard Rho properly factors 25, but it finds both factors of 5 at the same time, so it returns a factor of 25. That's correct, but not useful. So Pollard Rho will not find the factors of any power (square, cube, and so on).
Although I didn't run it, your Pollard Rho function looks okay. Wikipedia's advice to change the starting point might work, but generally doesn't. It is better, as Wikipedia also suggests, to change the random function g. The easiest way to do that is to increase the addend; instead of x²+1, use x²+c, where c is initially 1 and increases to 2, 3, … after each failure.
Here, as x can be as big as n-1, the product in your polynomialModN function will overflow.
computing x! can be very costly and might often result in overflow. Is there a way to find out whether x! is divisible by y or not without computing x!?
For y < x, its trivial;
But,for y > x, e.g. x = 5 and y = 60; I am struggling to find a way without computing x!
Compute the prime factorization of x! and y. You can do this without computing x! by factorizing every number from 2 to x and collecting all of the factors together. If the factors of y is a subset of the factors of x! then it is divisible.
If x and y are really large, so that it's not viable to iterate through all the numbers 1 to x, you can instead just factorize y and compute for every prime factor whether its maximum power in y also divides x!.
I've written about the algorithm more detailled in another answer.
Basically the check goes like this:
// computes maximum q so that p^q divides n!
bool max_power_of_p_in_fac(int p, int n) {
int mu = 0;
while (n/p > 0) {
mu += n/p;
n /= p;
}
return mu;
}
// checks whether y divides x!
bool y_divides_x_fac(int y, int x) {
for each prime factor p^q of y:
if (max_power_of_p_in_fac(p, x) < q)
return false;
return true;
}
This results in an algorithm for the case x < y of complexity O(time to factorize y + log x * #number of prime factors of y).
Obviously y can have at O(log y) prime factors. So with Pollard's rho factorization this would be something like O(y^(1/4) + log x * log y)
The correctness can be proven using this theorem:
For every i from 1 to x, update y /= gcd(y, i). The divisibility check at the end is y == 1.