cp-library

C++ Library for Competitive Programming

View the Project on GitHub emthrm/cp-library

:heavy_check_mark: 数学/平方剰余
(test/math/mod_sqrt.test.cpp)

Depends on

Code

/*
 * @title 数学/平方剰余
 *
 * verification-helper: PROBLEM https://judge.yosupo.jp/problem/sqrt_mod
 */

#include <iostream>

#include "emthrm/math/mod_sqrt.hpp"

int main() {
  int t;
  std::cin >> t;
  while (t--) {
    int y, p;
    std::cin >> y >> p;
    std::cout << emthrm::mod_sqrt(y, p) << '\n';
  }
  return 0;
}
#line 1 "test/math/mod_sqrt.test.cpp"
/*
 * @title 数学/平方剰余
 *
 * verification-helper: PROBLEM https://judge.yosupo.jp/problem/sqrt_mod
 */

#include <iostream>

#line 1 "include/emthrm/math/mod_sqrt.hpp"



#include <random>

#line 1 "include/emthrm/math/mod_pow.hpp"



namespace emthrm {

long long mod_pow(long long x, long long n, const int m) {
  if ((x %= m) < 0) x += m;
  long long res = 1;
  for (; n > 0; n >>= 1) {
    if (n & 1) res = (res * x) % m;
    x = (x * x) % m;
  }
  return res;
}

}  // namespace emthrm


#line 7 "include/emthrm/math/mod_sqrt.hpp"

namespace emthrm {

long long mod_sqrt(long long a, const int p) {
  if ((a %= p) < 0) a += p;
  if (a == 0) [[unlikely]] return 0;
  if (p == 2) [[unlikely]] return 1;
  if (mod_pow(a, (p - 1) >> 1, p) == p - 1) return -1;
  if (p % 4 == 3) return mod_pow(a, (p + 1) >> 2, p);
  int s = 1, q = (p - 1) >> 1;
  for (; !(q & 1); q >>= 1) {
    ++s;
  }
  static std::mt19937_64 engine(std::random_device {} ());
  std::uniform_int_distribution<> dist(2, p - 1);
  long long z;
  do {
    z = dist(engine);
  } while (mod_pow(z, (p - 1) >> 1, p) == 1);
  int m = s;
  long long c = mod_pow(z, q, p), r = mod_pow(a, (q - 1) >> 1, p);
  long long t = a * r % p * r % p;
  r = (r * a) % p;
  while (t != 1) {
    long long t2 = t * t % p;
    for (int i = 1; i < m; ++i) {
      if (t2 == 1) {
        const long long b = mod_pow(c, 1 << (m - i - 1), p);
        m = i;
        r = (r * b) % p;
        c = b * b % p;
        t = (t * c) % p;
        break;
      }
      t2 = (t2 * t2) % p;
    }
  }
  return r;
}

}  // namespace emthrm


#line 10 "test/math/mod_sqrt.test.cpp"

int main() {
  int t;
  std::cin >> t;
  while (t--) {
    int y, p;
    std::cin >> y >> p;
    std::cout << emthrm::mod_sqrt(y, p) << '\n';
  }
  return 0;
}
Back to top page