library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub maspypy/library

:heavy_check_mark: nt/crt.hpp

Depends on

Verified with

Code

#include "mod/mod_inv.hpp"
#include "nt/coprime_factorization.hpp"
#include "nt/factor.hpp"
#include "mod/barrett.hpp"

// 非負最小解を mod new_mod で返す (garner), なければ -1.
template <typename T>
i128 CRT(vc<T> vals, vc<T> mods, ll new_mod = -1, bool coprime = false) {
  int n = len(vals);
  FOR(i, n) { vals[i] = ((vals[i] %= mods[i]) >= 0 ? vals[i] : vals[i] + mods[i]); }

  bool ng = 0;
  auto reduction_by_factor = [&]() -> void {
    unordered_map<T, pair<T, T>> MP;
    FOR(i, n) {
      for (auto&& [p, e]: factor(mods[i])) {
        T mod = 1;
        FOR(e) mod *= p;
        T val = vals[i] % mod;
        if (!MP.count(p)) {
          MP[p] = {mod, val % mod};
          continue;
        }
        auto& [mod1, val1] = MP[p];
        if (mod > mod1) swap(mod, mod1), swap(val, val1);
        if (val1 % mod != val) {
          ng = 1;
          return;
        }
      }
    }
    mods.clear(), vals.clear();
    for (auto&& [p, x]: MP) {
      auto [mod, val] = x;
      mods.eb(mod), vals.eb(val);
    }
    n = len(vals);
  };
  auto reduction_by_coprime_factor = [&]() -> void {
    auto [basis, pfs] = coprime_factorization<T>(mods);
    int k = len(basis);
    vc<pair<T, T>> dat(k, {1, 0});
    FOR(i, n) {
      for (auto&& [pid, exp]: pfs[i]) {
        T mod = 1;
        FOR(exp) mod *= basis[pid];
        T val = vals[i] % mod;
        auto& [mod1, val1] = dat[pid];
        if (mod > mod1) swap(mod, mod1), swap(val, val1);
        if (val1 % mod != val) {
          ng = 1;
          return;
        }
      }
    }
    mods.clear(), vals.clear();
    for (auto&& [mod, val]: dat) { mods.eb(mod), vals.eb(val); }
    n = len(vals);
  };
  if (!coprime) { (n <= 10 ? reduction_by_coprime_factor() : reduction_by_factor()); }

  if (ng) return -1;
  if (n == 0) return 0;

  vc<ll> cfs(n);
  if (MAX(mods) < (1LL << 31)) {
    FOR(i, n) {
      Barrett bt(mods[i]);
      ll a = vals[i], prod = 1;
      FOR(j, i) {
        a = bt.modulo(a + cfs[j] * (mods[i] - prod));
        prod = bt.mul(prod, mods[j]);
      }
      cfs[i] = bt.mul(mod_inv(prod, mods[i]), a);
    }
  } else {
    FOR(i, n) {
      ll a = vals[i], prod = 1;
      FOR(j, i) {
        a = (a + i128(cfs[j]) * (mods[i] - prod)) % mods[i];
        prod = i128(prod) * mods[j] % mods[i];
      }
      cfs[i] = mod_inv(prod, mods[i]) * i128(a) % mods[i];
    }
  }
  i128 ret = 0, prod = 1;
  FOR(i, n) {
    ret += prod * cfs[i], prod *= mods[i];
    if (new_mod != -1) { ret %= new_mod, prod %= new_mod; }
  }
  return ret;
}
#line 1 "mod/mod_inv.hpp"

// long でも大丈夫
// (val * x - 1) が mod の倍数になるようにする
// 特に mod=0 なら x=0 が満たす
ll mod_inv(ll val, ll mod) {
  if (mod == 0) return 0;
  mod = abs(mod);
  val %= mod;
  if (val < 0) val += mod;
  ll a = val, b = mod, u = 1, v = 0, t;
  while (b > 0) {
    t = a / b;
    swap(a -= t * b, b), swap(u -= t * v, v);
  }
  if (u < 0) u += mod;
  return u;
}
#line 1 "nt/coprime_factorization.hpp"

/*
互いに素な整数 p1, p2, ..., pk を用いて n_i = prod p_i^e_i と表す.
input: [21,60,140,400], output: [3,7,20], [[(0,1),(1,1)],[(0,1),(2,1)],[(1,1),(2,1)],[(2,2)]]
O(N^2\log A) 程度. https://codeforces.com/blog/entry/108053
*/
template <typename T>
pair<vc<T>, vvc<pair<int, int>>> coprime_factorization(vc<T> nums) {
  vc<T> basis;
  for (T val: nums) {
    vc<T> new_basis;
    for (T x: basis) {
      if (val == 1) {
        new_basis.eb(x);
        continue;
      }
      vc<T> dat = {val, x};
      FOR(p, 1, len(dat)) {
        FOR(i, p) {
          while (1) {
            if (dat[p] > 1 && dat[i] % dat[p] == 0) dat[i] /= dat[p];
            elif (dat[i] > 1 && dat[p] % dat[i] == 0) dat[p] /= dat[i];
            else break;
          }
          T g = gcd(dat[i], dat[p]);
          if (g == 1 || g == dat[i] || g == dat[p]) continue;
          dat[i] /= g, dat[p] /= g, dat.eb(g);
        }
      }
      val = dat[0];
      FOR(i, 1, len(dat)) if (dat[i] != 1) new_basis.eb(dat[i]);
    }
    if (val > 1) new_basis.eb(val);
    swap(basis, new_basis);
  }

  sort(all(basis));

  vvc<pair<int, int>> res(len(nums));
  FOR(i, len(nums)) {
    T x = nums[i];
    FOR(j, len(basis)) {
      int e = 0;
      while (x % basis[j] == 0) x /= basis[j], ++e;
      if (e) res[i].eb(j, e);
    }
  }
  return {basis, res};
}
#line 1 "nt/factor.hpp"

#line 1 "random/base.hpp"

u64 RNG_64() {
  static u64 x_ = u64(chrono::duration_cast<chrono::nanoseconds>(
                      chrono::high_resolution_clock::now().time_since_epoch())
                          .count()) *
                  10150724397891781847ULL;
  x_ ^= x_ << 7;
  return x_ ^= x_ >> 9;
}

u64 RNG(u64 lim) {
  assert(lim > 0);
  return RNG_64() % lim;
}

ll RNG(ll l, ll r) {
  assert(l < r);
  return l + RNG_64() % (r - l);
}
#line 1 "other/bit.hpp"

int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
int popcnt_sgn(int x) { return (__builtin_parity(unsigned(x)) & 1 ? -1 : 1); }
int popcnt_sgn(u32 x) { return (__builtin_parity(x) & 1 ? -1 : 1); }
int popcnt_sgn(ll x) { return (__builtin_parityll(x) & 1 ? -1 : 1); }
int popcnt_sgn(u64 x) { return (__builtin_parityll(x) & 1 ? -1 : 1); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T>
T kth_bit(int k) {
  assert(0 <= k && k < int(8 * sizeof(T)));
  return T(1) << k;
}
template <typename T>
bool has_kth_bit(T x, int k) {
  assert(0 <= k && k < int(8 * sizeof(T)));
  return x >> k & 1;
}

template <typename UINT>
struct all_bit {
  static_assert(is_unsigned<UINT>::value);
  UINT s;
  all_bit(UINT s) : s(s) {}
  struct iter {
    UINT s;
    int operator*() const { return lowbit(s); }
    void operator++() { s &= s - 1; }
    bool operator!=(nullptr_t) const { return s; }
  };
  iter begin() const { return {s}; }
  nullptr_t end() const { return nullptr; }
};

template <typename UINT>
struct all_subset {
  static_assert(is_unsigned<UINT>::value);
  UINT s;
  all_subset(UINT s) : s(s) {}
  struct iter {
    UINT s, t;
    bool done = false;
    UINT operator*() const { return t; }
    void operator++() {
      done = (t == 0);
      t = (t - 1) & s;
    }
    bool operator!=(nullptr_t) const { return !done; }
  };
  iter begin() const { return {s, s}; }
  nullptr_t end() const { return nullptr; }
};

constexpr u64 full_mask(int n) {
  assert(0 <= n && n <= 64);
  return n == 64 ? -1ULL : (1ULL << n) - 1;
}

u64 bit_reverse(u64 x) {
  x = ((x & 0x5555555555555555ULL) << 1) | ((x >> 1) & 0x5555555555555555ULL);
  x = ((x & 0x3333333333333333ULL) << 2) | ((x >> 2) & 0x3333333333333333ULL);
  x = ((x & 0x0f0f0f0f0f0f0f0fULL) << 4) | ((x >> 4) & 0x0f0f0f0f0f0f0f0fULL);
  x = ((x & 0x00ff00ff00ff00ffULL) << 8) | ((x >> 8) & 0x00ff00ff00ff00ffULL);
  x = ((x & 0x0000ffff0000ffffULL) << 16) | ((x >> 16) & 0x0000ffff0000ffffULL);
  x = (x << 32) | (x >> 32);
  return x;
}
#line 1 "mod/montgomery_modint.hpp"

// odd mod.
// x の代わりに rx を持つ
template <int id, typename U1, typename U2>
struct Montgomery_modint {
  using mint = Montgomery_modint;
  inline static U1 m, r, n2;
  static constexpr int W = numeric_limits<U1>::digits;

  static void set_mod(U1 mod) {
    assert(mod & 1 && mod <= U1(1) << (W - 2));
    m = mod, n2 = -U2(m) % m, r = m;
    FOR(6) r *= 2 - m * r;
    r = -r;
    assert(r * m == U1(-1));
  }
  static U1 reduce(U2 b) { return (b + U2(U1(b) * r) * m) >> W; }

  U1 x;
  Montgomery_modint() : x(0) {}
  Montgomery_modint(U1 x) : x(reduce(U2(x) * n2)){};
  U1 val() const {
    U1 y = reduce(x);
    return y >= m ? y - m : y;
  }
  mint &operator+=(mint y) {
    x = ((x += y.x) >= m ? x - m : x);
    return *this;
  }
  mint &operator-=(mint y) {
    x -= (x >= y.x ? y.x : y.x - m);
    return *this;
  }
  mint &operator*=(mint y) {
    x = reduce(U2(x) * y.x);
    return *this;
  }
  mint operator+(mint y) const { return mint(*this) += y; }
  mint operator-(mint y) const { return mint(*this) -= y; }
  mint operator*(mint y) const { return mint(*this) *= y; }
  bool operator==(mint y) const {
    return (x >= m ? x - m : x) == (y.x >= m ? y.x - m : y.x);
  }
  bool operator!=(mint y) const { return not operator==(y); }
  mint pow(ll n) const {
    assert(n >= 0);
    mint y = 1, z = *this;
    for (; n; n >>= 1, z *= z)
      if (n & 1) y *= z;
    return y;
  }
};

template <int id>
using Montgomery_modint_32 = Montgomery_modint<id, u32, u64>;
template <int id>
using Montgomery_modint_64 = Montgomery_modint<id, u64, u128>;
#line 3 "nt/is_prime.hpp"

bool is_prime(const u64 x) {
  assert(x < u64(1) << 62);
  if (x == 2 or x == 3 or x == 5 or x == 7) return true;
  if (x % 2 == 0 or x % 3 == 0 or x % 5 == 0 or x % 7 == 0) return false;
  if (x < 121) return x > 1;
  const u64 d = (x - 1) >> lowbit(x - 1);

  using mint = Montgomery_modint_64<202311020>;

  mint::set_mod(x);
  const mint one(u64(1)), minus_one(x - 1);
  auto ok = [&](u64 a) -> bool {
    auto y = mint(a).pow(d);
    u64 t = d;
    while (y != one && y != minus_one && t != x - 1) y *= y, t <<= 1;
    if (y != minus_one && t % 2 == 0) return false;
    return true;
  };
  if (x < (u64(1) << 32)) {
    for (u64 a : {2, 7, 61})
      if (!ok(a)) return false;
  } else {
    for (u64 a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
      if (!ok(a)) return false;
    }
  }
  return true;
}
#line 4 "nt/factor.hpp"

template <typename mint>
ll rho(ll n, ll c) {
  assert(n > 1);
  const mint cc(c);
  auto f = [&](mint x) { return x * x + cc; };
  mint x = 1, y = 2, z = 1, q = 1;
  ll g = 1;
  const ll m = 1LL << (__lg(n) / 5);
  for (ll r = 1; g == 1; r <<= 1) {
    x = y;
    FOR(r) y = f(y);
    for (ll k = 0; k < r && g == 1; k += m) {
      z = y;
      FOR(min(m, r - k)) y = f(y), q *= x - y;
      g = gcd(q.val(), n);
    }
  }
  if (g == n) do {
      z = f(z);
      g = gcd((x - z).val(), n);
    } while (g == 1);
  return g;
}

ll find_prime_factor(ll n) {
  assert(1 < n && n < (1LL << 62));
  if (n % 2 == 0) return 2;
  if (is_prime(n)) return n;
  FOR(100) {
    ll m = 0;
    if (n < (1 << 30)) {
      using mint = Montgomery_modint_32<20231025>;
      mint::set_mod(n);
      m = rho<mint>(n, RNG(0, n));
    } else {
      using mint = Montgomery_modint_64<20231025>;
      mint::set_mod(n);
      m = rho<mint>(n, RNG(0, n));
    }
    if (is_prime(m)) return m;
    n = m;
  }
  assert(0);
  return -1;
}

// ソートしてくれる
vc<pair<ll, int>> factor(ll n) {
  assert(1 <= n && n < (1LL << 62));
  vc<pair<ll, int>> pf;
  FOR(p, 2, 100) {
    if (p * p > n) break;
    if (n % p == 0) {
      ll e = 0;
      do {
        n /= p, e += 1;
      } while (n % p == 0);
      pf.eb(p, e);
    }
  }
  while (n > 1) {
    ll p = find_prime_factor(n);
    ll e = 0;
    do {
      n /= p, e += 1;
    } while (n % p == 0);
    pf.eb(p, e);
  }
  sort(all(pf));
  return pf;
}

vc<pair<ll, int>> factor_by_spf(ll n, vc<int>& spf) {
  vc<pair<ll, int>> res;
  while (n > 1) {
    int p = spf[n];
    int e = 0;
    while (n % p == 0) {
      n /= p;
      ++e;
    }
    res.eb(p, e);
  }
  return res;
}
#line 1 "mod/barrett.hpp"

// https://github.com/atcoder/ac-library/blob/master/atcoder/internal_math.hpp
struct Barrett {
  u32 m;
  u64 im;
  explicit Barrett(u32 m = 1) : m(m), im(u64(-1) / m + 1) {}
  u32 umod() const { return m; }
  u32 modulo(u64 z) {
    if (m == 1) return 0;
    u64 x = (u64)(((unsigned __int128)(z)*im) >> 64);
    u64 y = x * m;
    return (z - y + (z < y ? m : 0));
  }
  u64 floor(u64 z) {
    if (m == 1) return z;
    u64 x = (u64)(((unsigned __int128)(z)*im) >> 64);
    u64 y = x * m;
    return (z < y ? x - 1 : x);
  }
  pair<u64, u32> divmod(u64 z) {
    if (m == 1) return {z, 0};
    u64 x = (u64)(((unsigned __int128)(z)*im) >> 64);
    u64 y = x * m;
    if (z < y) return {x - 1, z - y + m};
    return {x, z - y};
  }
  u32 mul(u32 a, u32 b) { return modulo(u64(a) * b); }
};

struct Barrett_64 {
  u128 mod, mh, ml;

  explicit Barrett_64(u64 mod = 1) : mod(mod) {
    u128 m = u128(-1) / mod;
    if (m * mod + mod == u128(0)) ++m;
    mh = m >> 64;
    ml = m & u64(-1);
  }

  u64 umod() const { return mod; }

  u64 modulo(u128 x) {
    u128 z = (x & u64(-1)) * ml;
    z = (x & u64(-1)) * mh + (x >> 64) * ml + (z >> 64);
    z = (x >> 64) * mh + (z >> 64);
    x -= z * mod;
    return x < mod ? x : x - mod;
  }

  u64 mul(u64 a, u64 b) { return modulo(u128(a) * b); }
};
#line 5 "nt/crt.hpp"

// 非負最小解を mod new_mod で返す (garner), なければ -1.
template <typename T>
i128 CRT(vc<T> vals, vc<T> mods, ll new_mod = -1, bool coprime = false) {
  int n = len(vals);
  FOR(i, n) { vals[i] = ((vals[i] %= mods[i]) >= 0 ? vals[i] : vals[i] + mods[i]); }

  bool ng = 0;
  auto reduction_by_factor = [&]() -> void {
    unordered_map<T, pair<T, T>> MP;
    FOR(i, n) {
      for (auto&& [p, e]: factor(mods[i])) {
        T mod = 1;
        FOR(e) mod *= p;
        T val = vals[i] % mod;
        if (!MP.count(p)) {
          MP[p] = {mod, val % mod};
          continue;
        }
        auto& [mod1, val1] = MP[p];
        if (mod > mod1) swap(mod, mod1), swap(val, val1);
        if (val1 % mod != val) {
          ng = 1;
          return;
        }
      }
    }
    mods.clear(), vals.clear();
    for (auto&& [p, x]: MP) {
      auto [mod, val] = x;
      mods.eb(mod), vals.eb(val);
    }
    n = len(vals);
  };
  auto reduction_by_coprime_factor = [&]() -> void {
    auto [basis, pfs] = coprime_factorization<T>(mods);
    int k = len(basis);
    vc<pair<T, T>> dat(k, {1, 0});
    FOR(i, n) {
      for (auto&& [pid, exp]: pfs[i]) {
        T mod = 1;
        FOR(exp) mod *= basis[pid];
        T val = vals[i] % mod;
        auto& [mod1, val1] = dat[pid];
        if (mod > mod1) swap(mod, mod1), swap(val, val1);
        if (val1 % mod != val) {
          ng = 1;
          return;
        }
      }
    }
    mods.clear(), vals.clear();
    for (auto&& [mod, val]: dat) { mods.eb(mod), vals.eb(val); }
    n = len(vals);
  };
  if (!coprime) { (n <= 10 ? reduction_by_coprime_factor() : reduction_by_factor()); }

  if (ng) return -1;
  if (n == 0) return 0;

  vc<ll> cfs(n);
  if (MAX(mods) < (1LL << 31)) {
    FOR(i, n) {
      Barrett bt(mods[i]);
      ll a = vals[i], prod = 1;
      FOR(j, i) {
        a = bt.modulo(a + cfs[j] * (mods[i] - prod));
        prod = bt.mul(prod, mods[j]);
      }
      cfs[i] = bt.mul(mod_inv(prod, mods[i]), a);
    }
  } else {
    FOR(i, n) {
      ll a = vals[i], prod = 1;
      FOR(j, i) {
        a = (a + i128(cfs[j]) * (mods[i] - prod)) % mods[i];
        prod = i128(prod) * mods[j] % mods[i];
      }
      cfs[i] = mod_inv(prod, mods[i]) * i128(a) % mods[i];
    }
  }
  i128 ret = 0, prod = 1;
  FOR(i, n) {
    ret += prod * cfs[i], prod *= mods[i];
    if (new_mod != -1) { ret %= new_mod, prod %= new_mod; }
  }
  return ret;
}
Back to top page