I basically need to have a function that finds that X is the result of a^b, and display a and b but I cannot use any available methods from math libraries.
-
9So, what have you researched and found so far? – PM 77-1 Apr 05 '16 at 01:48
-
I know how to recursively find if X is a perfect square and I know that the algorithm will have a complexity of log^3, but I'm stuck as to how it should be implemented in code – cheroz Apr 05 '16 at 02:07
-
1All numbers are of the form `a^b` for some `a` and `b`. What unstated assumptions are you making? I can guess, but specification-guessing is a potential source of bugs. – John Coleman Apr 05 '16 at 02:13
-
1That there should exist integers a and b > 1 that a^b is N, so for example if I enter 8, the function should give me 2, and 3, since 2^3 is 8. – cheroz Apr 05 '16 at 02:42
-
this page have already an answer for you, http://www.geeksforgeeks.org/check-if-a-number-can-be-expressed-as-xy-x-raised-to-power-y/ – Johnny Willer Apr 05 '16 at 03:14
-
@JohnnyWiller yes that page provides an exponential time solution, but there is a polynomial time solution (see my answer below) – TheGreatContini Apr 05 '16 at 03:45
2 Answers
Naive solution (pseudocode), looping over a (this is exponential time):
for (a = 2; a <= sqrt(X); ++a) {
b = round ( log ( X ) / log( a ) )
if (a^b == X) {
output solution
exit
}
}
output no solution found
Better solution (pseudocode), looping over b (this is polynomial time):
for (b = 2; b <= log(X)/log(2); ++b) {
a = round ( exp ( log(X)/b ) )
if (a^b == X) {
output solution
exit
}
}
output no solution found
Better solution in Python:
import math
def inv_power(x):
upper_limit = math.log(x)/math.log(2)
b = 2
while b <= upper_limit:
a = int(round( math.exp ( math.log(x)/b ) ) )
if a**b == x:
return a,b
b = b + 1
return None
Nice question. I'm disappointed so many people down voted it.
- 6,429
- 2
- 27
- 37
-
2I think the down-votes are simply for showing a lack of research. OP has simply stated the question and not shown any effort(s) to find a solution. I don't believe the down-votes reflect the quality of the core question. – Debosmit Ray Apr 05 '16 at 03:57
I assume integers (from comments) so without brute force I would try this:
use sieve of Eratosthenes
O(X.log(log(X)))Up to
sqrt(X)or half bits ofXnumber1<<(bits(X)>>1)to find primes you will be needing for this.scan all found primes
p(i)and check how many times you can divideXwith it.m=~X/ln(X); O(m)Remember the number of divisions as
n. Ifn<=1then ignore this primep(i)and continue with nextp(i+1). Ifn>1then add the primep(i)and itsnto some list;sort the
listbyndescendingO(m.log(m))now scan the
listfor solutionsq<=m; O(q^2)so for each entry in
listdivideX'=X/list[j].p^list[j].nand now checkX'the same way (using only entries with the samen). If you gotX'=1then stop the check and output your found result (power is usednandrootis multiplication of all used primes). You need to check all the combinations of primes with samenso recursion is the way. If no combination of entries with the samenfound with resulting inX'=1then move to entries with differentnwith starting fromXagain.
The recursion could look like this:
bool check(int X,int n,int j,int &a)
{
int i,x;
for (;(list[j].n==n)&&(j<list.size);j++) // scan all primes with the same `n`
{
for (x=X,i=0;i<n;i++) x/=list[j].p; // x=X/p^n
if (x==1) { a*=list[j].p; return true; }// stop you hit the result
if (check(x,n,j+1,a)) return true; // recursion
}
return false;
}
Where X is the number to check, n is actually checked power, j is starting entry in found list (no need to test previous entries as they have been already checked) and a is the base for power.If solution found returns true else false.
So now you just check all found powers with it and output/stop first found solution:
int a,n,j;
for (j=0,n=list[j].n;j<list.size;)
{
a=1; if (check(X,n,j,a)) return solution X=a^n;// check power `n`
while ((n==list[i].n)&&(j<list.size)) i++; // find next power
}
return no solution found;
You can combine some of these steps together especially #1,#2 (even avoid recursion). If you need floating or fixed point approach or want to add some additional ideas for integers see and the sub-link too:
Here very similar Q/A with C++ solution covering your questio: