最小化中国余数定理中的余数

时间:2011-06-28 02:26:25

标签: algorithm math complexity-theory chinese-remainder-theorem

我有多个包含多个同余的集合。

我试图在每组中的一个项目上应用Chinese remainder theorem时找到最小的余数。

例如有2套:

设置1:

  

7x + 1
  7x + 3

设置2:

  

11X
  11x + 2
  11x + 7
  11x + 8

7x + 1& 11x给出77x + 22 我在最小的余数之后(在上面的例子中是77x + 8 )而不必测试所有组合。


这是我实际问题的非常简化版本(约50集,每个约100个同余)。

我坚持如何处理这个问题,我们将非常感谢任何建议。

另外,如果我的数学术语不正确,我很抱歉。

2 个答案:

答案 0 :(得分:2)

有一种中间相遇算法可以找到时间上最小的残差

  

O(max(| S1 |,| S2 |)log(max(| S1 |,| S2 |)))。

首先使用Chinese Remainder Theoremt找到所有0的集合T1&lt; = t&lt; n1 * n2在S1中满足t mod n1且t mod n2 == 0 并且所有0的集合T2 <= u&lt; n1 * n2在S2中满足t mod n1 == 0和t mod n2。

即。在问题中给出的例子中:

  

T1 = {22,66}

     

T2 = {0,7,35,63}

现在你正在寻找的残差是总和(t1 + t2)mod n1 * n2,对于T1中的任何t1和T2中的t2。 因此,最小的残差要么是T1和T2中两个最小元素的总和,要么是两个仅略大于n1 * n2的元素。如果您对集合T1和T2进行排序,则可以通过扫描第一个集合从最小元素到最大元素并扫描从最大元素到最小元素的最大集合来找到第二个案例的最佳解决方案,即在T1中提升位置每当和小于n1 * n2时,只要它大于n1 * n2就减小T2中的位置。

如果你有两个以上的模n1 .. nk那么我能看到的最快解是将模数分成两组,比如n1 .. nr和nr + 1 .. nk找到集合T1使得t in对于所有1&lt; = i&lt; = r并且t mod ni == 0,对于所有r&lt; 1&lt; t mod ni == 0,在Si中的T1 iff t mod ni我&lt; = k。相应地定义T2。 复杂性取决于模量的分布,但通常应该是可能性数量的平方根。 Schroeppel和Shamir有一个算法可以节省一些内存,但不会降低时间复杂度。

对于您的应用,即50个模数和100个同余,该算法仍然使用大约100 ^ 25步,这是不可行的。不幸的是,看起来没有多项式算法。 特别地,已知找到方程x ^ 2 == a(mod n)的最小解x,其中 n是高度复合的整数,是NP完全的。但找到这样的解决方案可以减少你的问题。 因此,除非一致性具有一些可以被利用的特殊属性,否则你的问题一般也应该是NP完全的。

答案 1 :(得分:1)

设为S1,S2,... Sk,其中每组中的模数为n1> 1。 n2&gt; ...&gt; nk和Si中的剩余部分是a_i1&lt; a_i2&lt; ... 因此,例如: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。但这意味着%n2 = q(因为q是余数)。即a%n2应该在S2中。

算法的复杂度为O(n / n1 * | S1 | * k)。 这就是我选择n1成为最大模数的原因。但是如果你真的想要最小化复杂性,你应该以这样的方式选择集合Si,以便n / ni * | Si |在mimimal。