我正在寻找一个有效的问题算法,对于任何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)
}
}
如果可能,我正在寻找更好的算法(或任何语言的程序)。
答案 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-1
和j+1
,但即便如此,这也是 O(n)解决方案。
此外,您需要从i=1
跳过log(1) = 0
,这会导致被零除错误。换句话说,N=1
需要被视为特例。或者不被允许,因为N=1
的解决方案是i=1
和j=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,但只是说)