algorithm - 除法的最小公余数

标签 algorithm numbers

我有 n 对数字:( p[1], s[1] ), ( p[2], s[2] ), ... , ( p[n] , s[n] )

其中p[i]为大于1的整数; s[i] 是整数:0 <= s[i] < p[i]

有什么方法可以确定最小正整数 a ,这样对于每一对:

( s[i] + a ) mod p[i] != 0

还有比蛮力更好的方法吗?

最佳答案

有可能比蛮力做得更好。蛮力将是 O(A·n),其中 A 是我们正在寻找的 a 的最小有效值。

下面描述的方法使用 min-heap并达到O(n·log(n) + A·log(n))的时间复杂度。

首先,请注意用 (p[i] - s[i]) + k * p[i] 形式的值替换 a 会导致 a对于任何正整数 k,第 ith 对中的 reminder 等于零。因此,该表单的数字是无效的 a 值(我们正在寻找的解决方案不同于所有这些值)。

所提出的算法是一种生成该形式的数字的有效方法(对于所有 ik),无效值对于 a按递增顺序。一旦当前值与前一个值相差超过 1,就意味着中间有一个有效的 a

下面的伪代码详细介绍了这种方法。

1. construct a min-heap from all the following pairs (p[i] - s[i], p[i]), 
    where the heap comparator is based on the first element of the pairs.
2. a0 = -1; maxA = lcm(p[i])
3. Repeat
     3a. Retrieve and remove the root of the heap, (a, p[i]).
     3b. If a - a0 > 1 then the result is a0 + 1. Exit.
     3c. if a is at least maxA, then no solution exists. Exit.
     3d. Insert into the heap the value (a + p[i], p[i]).
     3e. a0 = a

备注:这样的a有可能不存在。如果在 LCM(p[1], p[2], ... p[n]) 下找不到有效的 a,则可以保证没有有效的 a 存在。


我将在下面展示该算法如何工作的示例

考虑以下 (p, s) 对:{ (2, 1), (5, 3) }。

第一对表明 a 应该避免像 1, 3, 5, 7, ... 这样的值,而第二对表明我们应该避免像这样的值2、7、12、17,...

最小堆最初包含每个序列的第一个元素(伪代码的第 1 步)——下面以粗体显示:

  • 1, 3, 5, 7, ...

  • 2, 7, 12, 17, ...

我们检索并移除堆头,,两个粗体中的最小值,这是1。我们将该序列中的下一个元素添加到堆中,因此堆现在包含元素 2 和 3:

  • 1, 3, 5, 7, ...

  • 2, 7, 12, 17, ...

我们再次获取堆头,这次它包含值 2,并将该序列的下一个元素添加到堆中:

  • 1, 3, 5, 7, ...

  • 2, 7, 12, 17, ...

算法继续,接下来我们将检索值3,并将5添加到堆中:

  • 1、3、5、7、...

  • 2, 7, 12, 17, ...

最后,现在我们检索值 5。此时我们意识到值 4 不在 a 的无效值中,因此这就是我们正在寻找的解决方案。

关于algorithm - 除法的最小公余数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48267700/

相关文章:

arrays - 最长 K 序贯递增子序列

algorithm - 乐高积木 - 动态规划

.net - 我如何生成这个特定的数字序列?

java - 如何按降序对字符串编号进行排序?

c++ - 在 C++ 中作为输入的函数

algorithm - 如何求解线性矩阵方程 : AX-XA=B efficiently?

python - 为什么这个线性分类器算法是错误的?

MySQL Ñ 拉丁字符(当行号适用时)

algorithm - 从一组数字中计算目标数字

JavaScript 从字符串中获取数字