编写算法以有效地找到任何给定N的所有i和j,使得N = i ^ j

时间:2015-11-03 07:14:05

标签: algorithm

我正在寻找一个有效的问题算法,对于任何N找到所有i和j,使得N = i ^ j

我可以按如下方式解决 O(N ^ 2)

for i=1 to N
{
 for j=1 to N
 {
  if((Power(i,j)==N)
    print(i,j)
 }
}

如果可能,我正在寻找更好的算法(或任何语言的程序)。

2 个答案:

答案 0 :(得分:5)

鉴于i^j=N,您可以通过双方的j来解决log的等式:
 j log(i) = log(N)j = log(N) / log(i)。因此算法变为

for i=2 to N
{
    j = log(N) / log(i)
    if((Power(i,j)==N)
       print(i,j)
}

请注意,由于浮点计算的舍入错误,您可能还需要检查j-1j+1,但即便如此,这也是 O(n)解决方案。

此外,您需要从i=1跳过log(1) = 0,这会导致被零除错误。换句话说,N=1需要被视为特例。或者不被允许,因为N=1的解决方案是i=1j=any value

正如M Oehm在评论中指出的,更好的解决方案是迭代j,并使用i计算pow(n,1.0/j)。这会将时间复杂度降低到 O(logN),因为j的最大值为log2(N)

答案 1 :(得分:1)

这是您可以使用的方法。

让我们说你必须解决一个等式:

a^b = n         //b and n are known

您可以使用二进制搜索找到它。如果,你得到一个条件,

x^b < n and (x+1)^b > n

然后,没有对(a,b)存在a^b = n

如果您在b的{​​{1}}范围内应用此方法,则应获得所有可能的对。

因此,此方法的复杂性为:O(log n * log n)

请按照以下步骤操作:

1..log(n)

此处,在算法中,function ifPower(n,b) min=1, max=n; while(min<max) mid=min + (max-min)/2 k = mid^b, l = (mid + 1)^b; if(k == n) return mid; if(l == n) return mid + 1; if(k < n && l > n) return -1; if(k < n) max = mid - 1; else min = mid + 2; //2 as we are already checking for mid+1 return -1; function findAll(n) s = log2(n) for i in range 2 to s //starting from 2 to ignore base cases, powers 0,1...you can handle them if required p = ifPower(n,i) if(b != -1) print(b,i) 表示a^b而非a raised to power of b(其obvs,但只是说)