-
Notifications
You must be signed in to change notification settings - Fork 0
/
34 Chinese Remainder Theorem.cpp
131 lines (99 loc) · 2.72 KB
/
34 Chinese Remainder Theorem.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
https://github.com/forthright48/code-library/blob/master/code_templates/chinese_remainder_theorem.cpp
**/
/** Which of the favors of your Lord will you deny ? **/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define MP make_pair
#define F first
#define S second
#define INF INT_MAX
#define PI 2*acos(0)
inline void optimizeIO()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
}
string to_str(LL x)
{
stringstream ss;
ss<<x;
return ss.str();
}
const int nmax = 1e7+7;
const LL LINF = 1e17;
/**
use __int128 data_type to avoid overflow
**/
/// ax + by = GCD(a,b)
/// r2 is GCD(a,b) and X & Y will be the co-eff of a and b respectively
LL ext_gcd ( LL A, LL B, LL &X, LL &Y )
{
LL x2, y2, x1, y1, x, y, r2, r1, q, r;
x2 = 1;
y2 = 0;
x1 = 0;
y1 = 1;
for (r2 = A, r1 = B; r1 != 0; r2 = r1, r1 = r, x2 = x1, y2 = y1, x1 = x, y1 = y )
{
q = r2 / r1;
r = r2 % r1;
x = x2 - (q * x1);
y = y2 - (q * y1);
}
X = x2;
Y = y2;
return r2;
}
/**
A CRT solver which works even when moduli are not pairwise coprime
1. Add equations using addEquation() method
2. Call solve() to get {x, N} pair, where x is the unique solution modulo N.
Assumptions:
1. LCM of all mods will fit into long long.
**/
class ChineseRemainderTheorem {
typedef long long vlong;
typedef pair<vlong,vlong> pll;
/** CRT Equations stored as pairs of vector. See addEqation()*/
vector<pll> equations;
public:
void clear() {
equations.clear();
}
/** Add equation of the form x = r (mod m)*/
void addEquation( vlong r, vlong m ) {
equations.push_back({r, m});
}
pll solve() {
if (equations.size() == 0) return {-1,-1}; /// No equations to solve
vlong a1 = equations[0].first;
vlong m1 = equations[0].second;
a1 %= m1;
/** Initially x = a_0 (mod m_0)*/
/** Merge the solution with remaining equations */
for ( int i = 1; i < equations.size(); i++ ) {
vlong a2 = equations[i].first;
vlong m2 = equations[i].second;
vlong g = __gcd(m1, m2);
if ( a1 % g != a2 % g ) return {-1,-1}; /// Conflict in equations
/** Merge the two equations*/
vlong p, q;
ext_gcd(m1/g, m2/g, p, q);
vlong mod = m1 / g * m2;
vlong x = ( (__int128)a1 * (m2/g) % mod *q % mod + (__int128)a2 * (m1/g) % mod * p % mod ) % mod;
/** Merged equation*/
a1 = x;
if ( a1 < 0 ) a1 += mod;
m1 = mod;
}
return {a1, m1};
}
};
int main()
{
optimizeIO();
}