一种最小化伪Diophantine方程的快速算法

时间:2012-01-25 22:20:07

标签: algorithm minimum number-theory

我们正在寻找一种在O(N)下解决这个问题的算法。

给出两个实数a和b(不失一般性,你可以假设它们都在0和1之间) 在-N和N之间找到一个最小化表达式的整数:

| a n - b - round(a n - b)|

我们认为欧几里得算法可能对此有效,但无法弄清楚。看起来应该有更快的方法来实现这一点,而不是通过对整数n进行详尽的搜索。

注意:在我们的情况下,a和b可能经常更改,因此可以修复查找表的a和b,它会变得有点难看,因为N也可以变化。还没有详细查看查询表,看看我们可以将它作为N的函数得到多小。

4 个答案:

答案 0 :(得分:1)

您正在有效地搜索使表达式aN - b尽可能接近整数的整数N. ab已修复吗?如果是,您可以预先计算查找表并使用O(1): - )

如果不考虑为所有整数aN寻找使I + b接近I的N.

答案 1 :(得分:1)

听起来你可能正在寻找像continued fractions ......

这样的东西

他们是如何相关的?假设您可以用有理数b1 / b2替换b。现在你正在寻找整数n和m,使得a-b1 / b2大约是m。换句话说,你正在寻找n和m使得(m +(b1 / b2))/ n =(mb2 + b1)/ nb1,一个有理数,大约是a。设置a1 = mb2 + b1和a2 = nb1。从连续的分数近似中找出a1和a2的值,并求解n和m。

另一种方法可能是:

  1. 找到a和b的良好有理逼近:a~a1 / a2和b~b1 / b2。
  2. 对n和m求解n(a1 / a2) - (b1 / b2)= m。
  3. 我不太确定它会起作用。 a所需的准确度取决于n和b。

答案 2 :(得分:1)

您可以计算比率a / b的连续分数。当分母大于N或者近似值足够好时,您可以停止。

// Initialize:
double ratio = a / b;
int ak = (int)(ratio);
double remainder = ratio - ak;

int n0 = 1;
int d0 = 0;

int n1 = ak;
int d1 = 1;

do {
    ratio = 1 / remainder;
    ak = (int)ratio;
    int n2 = ak * n1 + n0;
    int d2 = ak * d1 + d0;
    n0 = n1;
    d0 = d1;
    n1 = n2;
    d1 = d2;
    remainder = ratio - ak;
} while (d1 < N);

您要查找的n的值为d0(如果d1仍小于N,则为{{1}}。

这并不一定能给你最小的解决方案,但它可能是一个非常好的近似值。

答案 3 :(得分:0)

首先,让我们考虑一个更简单的情况,其中b = 0且0 <0。 a&lt; 1. F(a,n)= | an-round(an)|

让step_size = 1

Step 1. Let v=a
Step 2. Let period size p = upper_round( 1/v ).
Step 3. Now, for n=1..p, there must be a number i such that F(v,i) < v.
Step 4. v = F(v,i), step_size = stepsize * i
Step 5. Go to step 2

如您所见,您可以将F(v,*)降低到您想要的任何级别。最终解决方案n = step_size。