我有两个号码x1
和x2
。对于数字y
,我想计算x1
和x2
的公约数尽可能接近y
。
这是否有一个有效的算法?
我相信是时候重新解决我的问题并且更清楚了。这不是关于整数......
所以,假设我们有两个数字x1
和x2
。比如说,用户输入一个数字y
。我想要找到的是y'
接近y
的数字,以便x1 % y'
和x2 % y'
非常小(例如,小于0.02
,但是我们可以拨打这个号码LIMIT
)。换句话说,我不需要最优算法,但需要很好的近似。
我感谢你们所有的时间和精力,这真的很棒!
答案 0 :(得分:7)
我认为没有已知的有效(多项式时间)算法用于此问题,因为从integer factorization到此问题的多项式时间减少。由于没有已知的用于整数分解的多项式时间算法,因此对于您的问题也不可能有已知的算法,因为否则我们确实会有一个用于整数分解的多项式时间算法。
要了解其工作原理,假设您有一个您想要考虑的数字n。现在,使用您想要的任何算法,找到最接近√n的n和n的公因子。由于n的非平凡除数不能大于√n,因此找到(1)除以n的最大整数,或者(2)如果n为素数则为1。然后,您可以将n除以此数字并重复以生成n的所有因子。由于n最多只能有O(log n)个因子,因此对于你的问题,这最多需要求解器的多次迭代,因此我们有一个从整数因子分解到这个问题的多项式时间减少。如上所述,这意味着,至少在公开文献中,没有已知的有效经典算法来解决该问题。可能存在一个,但这将是一个非常重要的结果。
对于否定的答案感到抱歉,希望这会有所帮助!
答案 1 :(得分:2)
我认为你可以通过贪婪算法来做到这一点,首先通过常用算法找到GCD命名为d
(可以在对数时间内计算),然后在每次除d
时找到因子d
}到最小可用因子(创建d'
),并将|d'-y|
与|d-y|
进行比较,如果较小则以这种方式继续(并将d'
替换为d
),否则,将d'
乘以最小的消除因子,并再次将其距离与y进行比较。
答案 2 :(得分:2)
这很有效,因为我可以得到它:
from fractions import gcd
primes=[i for i in range(2,1000) if all(i%j!=0 for j in range(2,i))] #ensure you have enough primes.. (can improve efficency here)
def f(x1,x2,y):
_gcd=gcd(x1,x2)
if _gcd==1:
return 1
factors=(i for i in range(2,_gcd+1) if _gcd%i==0) #can improve efficiency here.. e.g. only go up to root(gcd)
r1=999999999
r2=999999999
for i in factors:
r1=min(r1,y%i)
r2=min(r2,i-y%i)
return y-r1 if r1<=r2 else y+r2
print f(8,4,3)
print f(16,12,5)
print f(997,53,44)
print f(2300*2,2300*3,57)
"""
2
4
1
56
"""
答案 3 :(得分:0)
x1
和x2
的GCD。 GCD <= Y
,则返回GCD
GCD
,最佳距离为GCD - y
。x1
和x2
找到GCD
public int getGCD( int a, int b )
{
return (b==0) ? a : gcd(b, a%b);
}
找到与y最接近的除数......
public int closestDivisor( int a, int b, int y ){
int gcd = getGCD( a, b );
if( gcd <= y ) return gcd;
int best = gcd - y;
for( int i = 0; i < best; i++ )
{
if( gcd % (i-y) == 0 ) return i - y;
if( gcd % (i+y) == 0 ) return i + y;
}
return gcd;
}
我认为唯一可用的额外优化是将gcd(可能使用筛子?)视为@trinithis建议的因素。