// a * x + b * y = gcd(a, b) long long extGcd(long long a, long long b, long long& x, long long& y) { if (b == 0) { x = 1; y = 0; return a; } else { int g = extGcd(b, a % b, y, x); y -= a / b * x; return g; } }
LL congruence( LL r1, LL m1, LL r2, LL m2) { extGcd(m1,m2); if( (r1 - r2 ) % G != 0) return -1; LL M = m1 * m2 / G; // Solution exists and is unique on LCM(m1,m2) = M LL K = ( r2 - r1) / G; LL ans = ((K * m1 * coeffA ) + r1) % M; // Note that K * (m1*coeffA + m2*coeffB) = r2-r1 if( ans < 0) ans += M; return ans; }
void extGcd(LL a, LL b) { if( b == 0 ) { G = a; coeffA = 1; coeffB = 0; } else { extGcd(b, a % b); coeffA -= coeffB * (a/b); swap(coeffA, coeffB); } }
int extGcd(int a, int b, int& x, int& y) { // returns d=gcd(a,b) and give x,y such that ax+by=d if (a == 0) { x = 0; y = 1; return b; } int a1, b1, c, x1, y1, rst; a1 = b % a; b1 = a; c = b / a; rst = extGcd(a1, b1, x1, y1); x = y1 - c * x1; y = x1; return rst; }
// ASSUME: gcd(a, m) == 1 long long modInv(long long a, long long m) { long long x, y; extGcd(a, m, x, y); return (x % m + m) % m; }