设集合为 S1, S2, ... Sk,其中每个集合中的模数为 n1 > n2 > ... > nk,Si 中的余数为 a_i1 < a_i2 < ... 例如:n1 = 11 , n2 = 7 和 S1 = {0, 2, 7, 8}, S2 = {1,3}
这是一个伪代码:
Find the target modulus, i.e. n = lcm(n1, n2, ..., nk)
Convert the sets Si into hashtables, so that you can check if a certain element is in the set or not.
for (int b = 0; b < n / n1; b++)
foreach (int c in [a_11, a_12, a_13, ...])
//candidate target reminder
a = b*n1 + c
works = true;
foreach (int ni in [n2, n3, ..., nk])
//test if there is an element in Si, which gives the correct reminder
//if not then this candidate doesn't work, go to the next
if( not Si contains (a % ni))
works = false;
break
if (works)
print "The solution is n*x+a"
exit
这个想法是寻找最小值。如果最小值是 a,那么 a 可以表示为 a=x*n1+y
,其中 y 是 S1 中的某个元素,因此我按升序迭代所有可能性。然后对于它们中的每一个,我检查其他集合 - 它们是否包含当前 a 满足的同余。假设第二组 S2:应该存在来自 S2 的同余,例如 p*n2+q,因此对于某个 p,a = p*n2+q。但这意味着 a % n2 = q(因为 q 是余数)。即 % n2 应该在 S2 中。
该算法的复杂度为 O (n/n1 * |S1| * k)。这就是为什么我选择 n1 作为最大模数。但是如果你真的想最小化复杂度,你应该选择集合 Si 使得 n/ni * |Si| 在最小的。