[英]Minimize the remainder in the chinese remainder theorem
我有多個包含多個同余的集合。
在將中國余數定理應用於每組中的一個項目時,我試圖找到最小的余數。
以 2 套為例:
設置 1:
7x + 1
7x + 3
第 2 組:
11倍
11x + 2
11 倍 + 7
11 倍 + 8
取 7x + 1 & 11x 得到 77x + 22 。
我追求最小的余數(在上面的例子中 77x + 8 ),而不必測試所有組合。
這是我實際問題的非常簡化的版本(約 50 組,每組約 100 個同余)。
我被困在如何解決這個問題上,任何建議將不勝感激。
另外,如果我的數學術語不正確,我深表歉意。
有一種中間相遇算法,可以及時找到最小的殘差
O(max(|S1|, |S2|) log(max(|S1|, |S2|)))。
先用中國剩余定理求S1中滿足t mod n1且t mod n2 == 0的所有0 <= t < n1*n2的集合T1和滿足t的所有0 <= u < n1*n2的集合T2 mod n1 == 0 和 S2 中的 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 中推進 position每當總和小於 n1*n2 並在 T2 中減小 position 時,只要它大於 n1*n2。
如果你有兩個以上的模數 n1.. nk,那么我能看到的最快的解決方案是將模數分成兩組,比如 n1.. nr 和 nr+1.. nk 找到集合 T1,使得 T1 中的 t iff t對於所有 1 <= i <= r 和 t mod ni 在 Si 中的 mod ni == 0 對於所有 r < i <= k。 相應地定義了 T2。 復雜性取決於模數的分布,但通常應該是可能性數量的平方根。 Schroeppel 和 Shamir 有一個算法,可以節省一些 memory,但不會降低時間復雜度。
對於您的應用程序,即 50 個模數和 100 個全等,此算法仍然使用大約 100^25 步,這是不可行的。 不幸的是,看起來沒有多項式算法。 特別是,已知找到方程 x^2 == a (mod n) 的最小解 x,其中 n 是高度復合 integer 是 NP 完全的。 但是找到這樣的解決方案可以減少你的問題。 因此,您的問題通常也應該是 NP 完全的,除非同余具有一些可以利用的特殊屬性。
設集合為 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| 在最小的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.