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 ofX
number1<<(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 divideX
with it.m=~X/ln(X); O(m)
Remember the number of divisions as
n
. Ifn<=1
then ignore this primep(i)
and continue with nextp(i+1)
. Ifn>1
then add the primep(i)
and itsn
to some list;sort the
list
byn
descendingO(m.log(m))
now scan the
list
for solutionsq<=m; O(q^2)
so for each entry in
list
divideX'=X/list[j].p^list[j].n
and now checkX'
the same way (using only entries with the samen
). If you gotX'=1
then stop the check and output your found result (power is usedn
androot
is multiplication of all used primes). You need to check all the combinations of primes with samen
so recursion is the way. If no combination of entries with the samen
found with resulting inX'=1
then move to entries with differentn
with starting fromX
again.
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: