$\newcommand{\O}{\mathrm{O}}$
Chinese Remainder Theorem(中国剰余定理) は $p_1$ と $p_2$ が互いに素で $x = q_1\ (\mathrm{mod}\ p_1), x = q_2\ (\mathrm{mod}\ p_2)$ が成り立つとき, これを満たす $x$ は $[0, p_1 p_2)$ にただ一つ存在するという定理のことであり, 以下の実装は実際にその唯一の解を求めるアルゴリズムである
結局式変形すると拡張ユークリッドの互除法(extgcd)を解くことと同じであることが分かり, それを実装する. 以下の実装では一般の場合(法が互いに素でない場合)に拡張したものも含まれている.
時間計算量: $\O (\log p)$ ($p$ は法の値)
template<typename T> T gcd(T a,T b) { if(a % b == 0){ return b; }else{ return gcd(b,a%b); } } template <typename T> void extgcd(T a, T b, T& x, T& y) { if(b != 0){ extgcd(b,a%b,y,x); y -= (a/b)*x; }else{ x = 1; y = 0; } } // (value, mod) // 型 T は積が収まるようにとる(引数が int なら long long にする) template <typename T> pair<T, T> CRT(const pair<T, T>& a1, const pair<T, T>& a2) { const T v1 = a1.first, m1 = a1.second; const T v2 = a2.first, m2 = a2.second; if(v1 == v2) return make_pair(v1,m1*m2); T x, y; extgcd(m1, m2, x, y); x *= (v2 - v1), y *= (v2 - v1); const T m = m1 * m2; const T res = ((m1 * (x % m2)) + v1) % m; return make_pair((res >= 0 ? res : res + m), m); } //modどうしが互いに素でないとき //(value, mod) // template <typename T> // pair<T, T> CRT(const pair<T, T>& a1, const pair<T, T>& a2) // { // const T v1 = a1.first, m1 = a1.second; // const T v2 = a2.first, m2 = a2.second; // T g = gcd(m1, m2); // T dev = (v2 - v1) / g; // T mod = abs(v2 - v1) % g; // if(mod) return make_pair(-1,-1); // T x, y; // extgcd(m1 / g, m2 / g, x, y); // x *= dev, y *= dev; // const T m = m1 / g * m2; // const T res = ((m1 * (x % (m2 / g))) + v1) % m; // return make_pair((res >= 0 ? res : res + m), m); // }