セットを 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によって満たされる合同が含まれているかどうか。2 番目のセット S2 について言えば、S2 からの合同が存在する必要があります。たとえば、p*n2+q で、ある p に対して a = p*n2+q となります。しかし、これは a % n2 = q を意味します (q は剰余であるため)。つまり、% n2 は S2 にあるはずです。
アルゴリズムの複雑さは O (n/n1 * |S1| * k) です。そのため、n1 を最大のモジュラスとして選択しました。しかし、本当に複雑さを最小限に抑えたい場合は、n/ni * |Si| となるような方法でセット Si を選択する必要があります。最小で。