Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Chinese Remainder Theorem

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for poyo poyo
November 24, 2018
140

Chinese Remainder Theorem

Avatar for poyo

poyo

November 24, 2018
Tweet

Transcript

  1. 中国剰余定理(CRT) m , m :互いに素な正整数、a , a ∈ Z に対して連立方程式

    を満たす x (0 ≤ x < m m ) が存在する のでそれを求める 1 2 1 2 x ≡ a mod. m 1 1 x ≡ a mod. m 2 2 1 2
  2. x := a とすれば1つ目の式は満たされる このとき x + (a − x)m

    t も1つ目の式を満たすが、もし m t = 1 − m t とできれば2つ目の式も満たす m ∤ (a − x) なら x が打ち消し合って m での剰余は a の みが残るのでok m ∣ (a − x) なら x が残るが x ≡ a mod. m なのでok m , m は互いに素だから m t + m t = 1 となる t , t は拡張 ユークリッドの互除法で求められる 1 2 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 1 2
  3. 実装例 (ruby) def crt(a1, a2, m1, m2) x, y, g

    = ext_gcd(m1, m2) # g == 1 じゃないとダメ (a1 + (a2 - a1) * m1 * g) % (m1 * m2) end 実装例 (C++) using i64 = int64_t; i64 crt(i64 a1, i64 a2, i64 m1, i64 m2) { auto xyg = ext_gcd(m1, m2); // xyg[2] == 1 じゃないとダメ auto ret = a1 + (a2 - a1) % m2 * m1 * xyg[0] % m2, m = m1 * m2; return (ret % m + m) % m; }
  4. 実装の注意 (C++) % m2 しておかないと、3つの数の積なのですぐオーバーフローする t , t が m

    t + m t = 1 を満たすなら t ← t + km としても解になる(t のほうを調整すればいい) なので互除法で得られる解がめちゃでかくなりうる t ← t %m しとけば m 未満になる ついでに a − a も m で mod をとっておく 上の考察で割り切れるかどうかはどうでもいいことが分か ったので mod をとっていい ret % m は ret が負のときいやな感じになる -17 % 5 = -2 になる ruby などは -17 % 5 = 3 になる 1 2 1 1 2 2 1 1 2 2 1 1 2 2 2 1 2
  5. 法が互いに素とは限らない場合 を満たす x が存在する必要十分条件は a ≡ a mod. gcd(m ,

    m ) である。また、x は 0 ≤ x < lcm(m , m ) の範囲で一意 x ≡ a mod. m 1 1 x ≡ a mod. m 2 2 1 2 1 2 1 2
  6. 互いに素のときと同じ a + (a − a )m t が解になってほしい いま、m

    t = g − m t where g := gcd(m , m ) とできる さらに g ∣ (a − a ) が成り立っているから、結局、微妙に変更して a + m t とすれば解になる mod. m が a になるのは良い 式変形すると a + (a − a ) − m t となるの で、互いに素のときと同じ考察で mod. m で a と分かる 1 2 1 1 1 1 1 2 2 1 2 2 1 1 g a − a 2 1 1 1 1 1 1 { 2 1 g a − a 2 1 2 2 } 2 2
  7. 実装例 (ruby) def crt(a1, a2, m1, m2) x, y, g

    = ext_gcd(m1, m2) return [-1, 0] if (a1 - a2) % g > 0 # 解なし lcm = m1 * m2 / g [(a1 + (a2 - a1) / g * m1 * x) % lcm, lcm] end
  8. n 個の連立方程式の場合 それぞれの方程式が x ≡ a mod. m の形で表されるとすると、解が存在する条件は ∀i,

    j に対して a ≡ a mod. gcd(m , m ) が成り立つこと 実装する際は、前から2つ方程式を取ってきて解いた結果を新しく制約と していけばいい i i i j i j
  9. 例. a = [2, 3, 3] m = [3, 5,

    10] ans, mod = 0, 1 # 任意の整数は mod. 1 で 0 a.zip(m).each do |aa, mm| ans, mod = crt(ans, aa, mod, mm) end puts ans # => 23 x x x ≡ 2 mod. 3 ≡ 3 mod. 5 ≡ 3 mod. 10