This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub kmyk/competitive-programming-library
/**
* @brief extended gcd
* @description for given a and b, find x, y and gcd(a, b) such that ax + by = 1
* @note O(log n)
* @see https://topcoder.g.hatena.ne.jp/spaghetti_source/20130126/1359171466
*/
tuple<ll, ll, ll> extgcd(ll a, ll b) {
ll x = 0, y = 1;
for (ll u = 1, v = 0; a; ) {
ll q = b / a;
x -= q * u; swap(x, u);
y -= q * v; swap(y, v);
b -= q * a; swap(b, a);
}
return make_tuple(x, y, b);
}
unittest {
random_device device;
default_random_engine gen(device());
REP (iteration, 1000) {
ll a = uniform_int_distribution<ll>(1, 10000)(gen);
ll b = uniform_int_distribution<ll>(1, 10000)(gen);
ll x, y, d; tie(x, y, d) = extgcd(a, b);
assert (a * x + b * y == d);
assert (d == __gcd(a, b));
}
}
/**
* @note recursive version (slow)
*/
pair<int, int> extgcd_recursive(int a, int b) {
if (b == 0) return { 1, 0 };
int na, nb; tie(na, nb) = extgcd(b, a % b);
return { nb, na - a/b * nb };
}
/**
* @note x and m must be relatively prime
* @note O(log m)
*/
ll modinv(ll x, int m) {
assert (1 <= x and x < m);
ll y, d; tie(y, ignore, d) = extgcd(x, m);
if (d != 1) return 0; // no inverse
assert (x * y % m == 1);
return (y % m + m) % m;
}
/**
* @brief chinese remainder theorem
* @note the unit element is (0, 1)
*/
pair<ll, ll> crt(pair<ll, ll> eqn1, pair<ll, ll> eqn2) {
ll x1, m1; tie(x1, m1) = eqn1;
ll x2, m2; tie(x2, m2) = eqn2;
ll x = x1 + m1 * (x2 - x1) * modinv(m1 % m2, m2);
ll m = m1 * m2;
return { (x % m + m) % m, m };
}
ll multmod(ll a, ll b, ll m) {
a = (a % m + m) % m;
b = (b % m + m) % m;
ll c = 0;
REP (i, 63) {
if (b & (1ll << i)) {
c += a;
if (c > m) c -= m;
}
a *= 2;
if (a > m) a -= m;
}
return c;
}
pair<ll, ll> crt(pair<ll, ll> eqn1, pair<ll, ll> eqn2) {
ll x1, m1; tie(x1, m1) = eqn1;
ll x2, m2; tie(x2, m2) = eqn2;
if (m1 == 0 or m2 == 0) return make_pair(0ll, 0ll);
assert (1 <= m1 and 1 <= m2);
ll m1_inv, d; tie(m1_inv, ignore, d) = extgcd(m1, m2);
if ((x1 - x2) % d) return make_pair(0ll, 0ll);
ll m = m1 * m2 / d;
// ll x = x1 + (m1 / d) * (x2 - x1) % m * (m1_inv % m) % m;
ll x = x1 + multmod(multmod(m1 / d, x2 - x1, m), m1_inv, m);
return make_pair((x % m + m) % m, m);
}
#line 1 "old/extgcd.inc.cpp"
/**
* @brief extended gcd
* @description for given a and b, find x, y and gcd(a, b) such that ax + by = 1
* @note O(log n)
* @see https://topcoder.g.hatena.ne.jp/spaghetti_source/20130126/1359171466
*/
tuple<ll, ll, ll> extgcd(ll a, ll b) {
ll x = 0, y = 1;
for (ll u = 1, v = 0; a; ) {
ll q = b / a;
x -= q * u; swap(x, u);
y -= q * v; swap(y, v);
b -= q * a; swap(b, a);
}
return make_tuple(x, y, b);
}
unittest {
random_device device;
default_random_engine gen(device());
REP (iteration, 1000) {
ll a = uniform_int_distribution<ll>(1, 10000)(gen);
ll b = uniform_int_distribution<ll>(1, 10000)(gen);
ll x, y, d; tie(x, y, d) = extgcd(a, b);
assert (a * x + b * y == d);
assert (d == __gcd(a, b));
}
}
/**
* @note recursive version (slow)
*/
pair<int, int> extgcd_recursive(int a, int b) {
if (b == 0) return { 1, 0 };
int na, nb; tie(na, nb) = extgcd(b, a % b);
return { nb, na - a/b * nb };
}
/**
* @note x and m must be relatively prime
* @note O(log m)
*/
ll modinv(ll x, int m) {
assert (1 <= x and x < m);
ll y, d; tie(y, ignore, d) = extgcd(x, m);
if (d != 1) return 0; // no inverse
assert (x * y % m == 1);
return (y % m + m) % m;
}
/**
* @brief chinese remainder theorem
* @note the unit element is (0, 1)
*/
pair<ll, ll> crt(pair<ll, ll> eqn1, pair<ll, ll> eqn2) {
ll x1, m1; tie(x1, m1) = eqn1;
ll x2, m2; tie(x2, m2) = eqn2;
ll x = x1 + m1 * (x2 - x1) * modinv(m1 % m2, m2);
ll m = m1 * m2;
return { (x % m + m) % m, m };
}
ll multmod(ll a, ll b, ll m) {
a = (a % m + m) % m;
b = (b % m + m) % m;
ll c = 0;
REP (i, 63) {
if (b & (1ll << i)) {
c += a;
if (c > m) c -= m;
}
a *= 2;
if (a > m) a -= m;
}
return c;
}
pair<ll, ll> crt(pair<ll, ll> eqn1, pair<ll, ll> eqn2) {
ll x1, m1; tie(x1, m1) = eqn1;
ll x2, m2; tie(x2, m2) = eqn2;
if (m1 == 0 or m2 == 0) return make_pair(0ll, 0ll);
assert (1 <= m1 and 1 <= m2);
ll m1_inv, d; tie(m1_inv, ignore, d) = extgcd(m1, m2);
if ((x1 - x2) % d) return make_pair(0ll, 0ll);
ll m = m1 * m2 / d;
// ll x = x1 + (m1 / d) * (x2 - x1) % m * (m1_inv % m) % m;
ll x = x1 + multmod(multmod(m1 / d, x2 - x1, m), m1_inv, m);
return make_pair((x % m + m) % m, m);
}