假设我们给出了一个复合数( n > 3),可以写成:n = a*b
,其中a和b是任意整数。
现在,我们的任务是计算 a &的价值。 b ,以使函数f(a,b) = |a-b|
最小化。
int n;
cin >> n; // Take it from the user
/* Now, find the value of the a and b */
int a = 1;
int b = n;
int temp_a;
int temp_b;
for(temp_a=1; temp_a<=sqrt(n); temp_a++) {
if(n % temp_a == 0) {
temp_b = n / temp_a;
if((temp_b - temp_a) < (b - a)) {
b = temp_b;
a = temp_a;
}
}
}
print a and b
答案 0 :(得分:2)
您希望找到 N 的最大除数不大于 sqrt(N)。最简单的方法是迭代所有可能的除数并检查它们。在最坏的情况下,它需要 O(sqrt(N))时间。
不幸的是,在最坏的情况下,无法在 O(log N)时间内解决此问题。事实上,即使在任何 p 的 O((log N)^ p)时间内也无法做到这一点。很容易证明,如果可能,那么你将能够在其大小的多项式时间内找到任意数字的prime factorization,以字节为单位。没有人能够立刻做到这一点,并且有一个广泛使用的RSA cryptosystem,它强烈依赖于这样一个事实:没有人可以如此快速地将数字分解。这是每个人都害怕quantum computers =)
的原因之一但是,有些算法渐近地比 O(sqrt(N))快。此外,还有一些更快的启发式算法用于分解。我强烈建议在这件事上阅读wikipedia article。
稍微提高复杂性的方法之一是预先计算所有素数到 sqrt(N)。然后,如果您尝试仅将它们除以 N ,您将能够找到 N 的素数因子分解。知道素数因子分解后,您可以使用递归搜索有效地迭代所有可能的除数。找到因子分解所花费的时间与检查质数一样多,即 O(sqrt(N)/ log(N))。迭代所有除数需要的时间与这些除数的数量成正比,即 N 的asymptotically less than any polynomial。
答案 1 :(得分:2)
我花了很多时间为这个问题找到最佳解决方案,但失败了。然后我试着测试@ psyco的方法是否更好或@ Nyavro的。我个人认为从sqrt(n) to 1
向下倒数必须更好但是要检查@psyco的论点,我在python程序中实现了两种方法并绘制了一个图表来比较两者可以用来寻找解决方案的迭代次数。该图适用于4到10000之间的所有复合数。下面是我的Python实现:
import matplotlib.pyplot as plt
import math
X = 10001
n1 = [0]*X
n2 = []
for i in range(2, int(math.sqrt(X))+1):
if n1[i] == 0:
for j in range(i*i, X, i):
n1[j] = 1
for i in range(4, X):
if n1[i] == 1:
n2.append(i)
#print n2
count = []
count2 = []
for n in n2:
a = 1
b = n
c = 0
flag = 0
for ta in range(int(math.sqrt(n)), 0, -1):
c += 1
if n % ta == 0:
tb = n / ta
flag = 1
if tb-ta <= b-a:
a = ta
b = tb
if flag == 1:
break
count.append(c)
a = 1
b = n
c = 0
for ta in range(1, int(math.sqrt(n))+1):
c += 1
if n % ta == 0:
tb = n / ta
if tb-ta <= b-a:
a = ta
b = tb
count2.append(c)
plt.plot(n2, count, 'o')
plt.plot(n2, count2, 'o')
plt.show()
这是输出图:
上面的绿色边框是@ psyco的代码,而蓝色边框是@ Nyavro的方法。尽管在很多情况下@ Nyavro的方法更好,但它们在很多情况下都需要几乎相同的时间。
答案 2 :(得分:1)
考虑不是从1到sqrt(n)迭代,而是从sqrt(n)向下迭代到1.首先找到除数给出答案,你不需要继续进行