views:

140

answers:

5

To understand the problem,let us consider these examples first:

                                 46 = (22)6 = 212 = (23)4 = 84 = 163 = 4096.

Thus,we can say that 46,212,84 and 163 are same.

                                 273 = 39 = 19683

so, both 273 and 39 are identical.

Now the problem is, for any given pair of ab how to compute all others possible (if any)xy where, ab = xy.I am interested in an algorithm that can be efficiently implemented in C/C++.

For example:

If the inputs are like this:

4,6 desired output :(2,12),(8,4)

8,4 desired output :(2,12),(2,6)

27,3 desired output :(3,9)

12,6 desired output :(144,3),(1728,2)

7,5 desired output : No duplicate possible

+2  A: 

If integers is the only thing you're interested in, you could just start extracting integer roots from the target number, and checking if the result is an integer.

You even have a convenient stop condition - whenever the root is below 2 you can stop. That is, the algorithm:

  • Given a result
  • N <- 2
  • Compute Nth root.
    • If it's an integer: add to answers
    • If it's < 2, exit loop
  • N += 1, back to previous step

This algorithm will always terminate.

Eli Bendersky
That will be too naive thing to do. How to do it without computing a^b ?
nthrgeek
I think this solution is not naïve at all. In fact, I think if implemented using integer arithmetic only (and not floating point as is insinuated), this solution would work quite well.
Dietrich Epp
@ Dietrich Epp: Well could you please mention,how can we avoid floating point calculation here ?
nthrgeek
So the subproblem is: for integers N and X, determine if X has an integer Nth root, and if so compute it. You can, for example, use a bisection algorithm to find the answer. Starting with the crudest bounds of 1 and X, you can compute (estimate)^N power and see if it is less than, equal to, or greater than X, and adjust the bounds based on that comparison.
GregS
@ Dietrich Epp: I can't understand why you dissed my answer and praised this one, since they're identical except for the issue of counting the loop up rather than down.
Carl Smotricz
A: 

The smallest base that makes sense is 2. Also, the smallest exponent that makes sense is 2.

Given the result, you can determine the largest possible exponent.

Example: 4096 = 2^12, biggest exponent is 12.

This also works with results that aren't powers of 2: 19683 is a bit bigger than 2^14, so you won't be seeing any exponents bigger than 14.

Now you can take your number and work your way down from the top exponent toward 2 (the smallest exponent). For every trial exponent exp, take the exp-th root of the result; if that comes out as a clean integer, then you've found one solution.

You can use logarithms to calculate the log2 of a result, and to take the n-th root of a number. But you will need to watch out for rounding errors.

The advantage of this approach is that once you've set things up, you can just run down a simple loop, and once done you have all your results.

Carl Smotricz
I think it is a mistake to use floating point numbers to solve a problem involving integers in number theory. Any algorithm using floating point will fail outright (give incorrect results) given a sufficiently large input, where it becomes impossible to distinguish a rounding error from a negative result.
Dietrich Epp
Well why you deleted your other solution ? I didn't get what you meant in `step 2` ?!!
nthrgeek
@Dietrich: If you know to watch out for rounding errors you can avoid the problem by (a) rounding and (b) checking your result using integer math. I agree that a solution based on prime factorization will be more effective; this is just an alternative solution.
Carl Smotricz
@nthrgeek: My other answer was a prime factorization approach, but poorly explained. Others were better, so I decided to delete rather than elaborate.
Carl Smotricz
+1  A: 

I believe that this problem is equivalent to the Integer factorization problem.

I said this because we can convert any composite number to a unique product of prime numbers
(see Fundamental theorem of arithmetic) and then start creating combinations with the factors and the powers.

Update: for example: 46

we convert it to a power of a prime factor, so we have 212.
Now we increase the base exponentially and we have: 46, 84 ... until the exponent becomes 1.

Nick D
I know about integer factorization.Thanks :) Could you please explain :`then start creating combinations with the factors and the powers.` ?
nthrgeek
+5  A: 

This is mostly a math problem. You can extract all the prime factors of a number, and you'll get a list of prime numbers and their exponents, i.e., 216000 = 26 * 33 * 53. Then take the GCD of the exponents: GCD(6,3,3) = 3. Divide the exponents by the GCD to get the smallest root of the number, 22 * 31 * 51 = 60. Then factor the GCD — factors of 3 are 1 and 3. There is one way to express the number as an integral power for each factor of the GCD. You can express it as (603)1 or (601)3.

EDIT: fixed math error.

Dietrich Epp
For 4096 : 2^12 then ?
nthrgeek
The GCD of `(12)` is trivially 12. The smallest root is then 2^1. Factors of 12 are `(1, 2, 3, 4, 6, 12)`, so you can express it as `(2^1)^12 = 2^12, (2^2)^6 = 4^6, (2^3)^4 = 8^4`
caf
It's perhaps obvious, but you can avoid dealing with extremely large numbers if you don't first compute the result number but simply directly do the factorization on the base: after all, any resultant GCD of it's factorization can simply be included in the exponent and then it's back to business as usual for this solution. in short; factorize base; GCD factorization's exponents to minimize base, con GCD factors of base-factorization's exponents with factorization of input-exponent, iterate over all possible factorizations of exponent.
Eamon Nerbonne
@Eamon Nerbonne: Could you please elaborate ?
nthrgeek
e.g.: 144^4; factorize the base and exponent separately: (2^4*3^2)^(2^2); GCD the base and extract common exponent: ((2^2*3^1)^2)^(2^2); rewrite the shared exponent of the base as part of the "official" exponent: (2^2*3^1)^(2*2^2) == 12^(2^3) ; now it's just a matter of listing all possible factors of the exponent; i.e. 1, 2^1, 2^2 and 2^3. The speedup here lies in the fact that you avoid dealing with large numbers (certainly until the last possible moment), and if you accept output in the form of (12^8)^1, you don't need to compute the large numbers at all.
Eamon Nerbonne
A: 

I finally solved it myself.Using a naive integer factorization algorithm my solution look like this.It can be optimized further by using Pollard's rho algorithm

EDIT: Code updated, now it can handle composite bases.Please point if it has certain other bugs too :)

nthrgeek
@ Negative voter : Can you state the reason ?
nthrgeek
I didn't vote, so I'm just guessing that the down votes are because you do not give credit to any of the answers. For example, Dietrich Epp describes completely correct answer. Eli Bendersky additionally shows how to avoid the integer factorization. Your answers sounds like all this was not helpful to you.
abc
@ abc : Did you checked my solution ? No offense to others but didn't used what was stated here still now.
nthrgeek
Your program doesn't look correct. It only uses the exponent of the first prime. Did you test your program with composite bases? What is the output for a case like (12, 6)?
abc
@abc: Thanks for pointing.Code updated :)
nthrgeek