ACM_Notebook_new

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

View the Project on GitHub ngthanhtrung23/ACM_Notebook_new

:heavy_check_mark: Math/tests/sqrt_mod.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/sqrt_mod"

#include <bits/stdc++.h>
using namespace std;

// for 64-bit, use mt19937_64
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
long long get_rand(long long r) {
    return uniform_int_distribution<long long> (0, r-1)(rng);
}

#include "../NumberTheory/SqrtMod.h"

int32_t main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int ntest; cin >> ntest;
    while (ntest--) {
        long long n, p; cin >> n >> p;
        long long res = sqrtMod(n, p);
        cout << res << '\n';
    }
    return 0;
}
#line 1 "Math/tests/sqrt_mod.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/sqrt_mod"

#include <bits/stdc++.h>
using namespace std;

// for 64-bit, use mt19937_64
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
long long get_rand(long long r) {
    return uniform_int_distribution<long long> (0, r-1)(rng);
}

#line 1 "Math/NumberTheory/SqrtMod.h"
// sqrtMod(X, q), with q is prime, returns:
// a where a*a = X
// -1 if no solution
//
// Note:
// - there are either 1 or 2 solutions, a and p - a (which can be same).
//   This code return smaller solution
//
// Copied from https://judge.yosupo.jp/submission/59210
//
// Tested:
// - (p <= 10^9) https://judge.yosupo.jp/problem/sqrt_mod
// - (print all sols) https://oj.vnoi.info/problem/jacobi
// - https://oj.vnoi.info/problem/newj

// sqrtMod {{{
using ll = long long;
ll euclid(ll x, ll y, ll &k, ll &l) {
    if (y == 0) {
        k = 1;
        l = 0;
        return x;
    }
    ll g = euclid(y, x % y, l, k);
    l -= k * (x / y);
    return g;
}

ll mult(ll x, ll y, ll md) {
    return x * y % md;
}
ll bin_pow(ll x, ll p, ll md) {
    if (p == 0) return 1;
    if (p & 1) return mult(x, bin_pow(x, p - 1, md), md);
    return bin_pow(mult(x, x, md), p / 2, md);
}

ll Cipolla(ll X, ll q) {
    ll pw = (q - 1) / 2;
    int K = 60;
    while((1LL << K) > pw) K--;
    while(true) {
        ll t = get_rand(q);
        ll a = 0, b = 0, c = 1;
        for (int k = K; k >= 0; k--) {
            a = b * b % q;
            b = 2 * b * c % q;
            c = (c * c + a * X) % q;
            if (((pw >> k) & 1) == 0) continue;
            a = b;
            b = (b * t + c) % q;
            c = (c * t + a * X) % q;
        }
        if (b == 0) continue;
        c = (c + q - 1) % q;
        ll k, l;
        euclid(b, q, k, l);
        c = -c * k % q;
        if (c < 0) c += q;
        if (c * c % q == X) return c;
    }
    assert(false);
}

ll sqrtMod(ll X, ll q) {
    X %= q;
    if (q == 2 || X == 0) return min(X, q-X);
    if (bin_pow(X, (q - 1) / 2, q) != 1) return -1;
    if (q % 4 == 3) {
        ll res = bin_pow(X, (q + 1) / 4, q);
        return min(res, q - res);
    }
    auto res = (Cipolla(X, q) % q + q) % q;
    return min(res, q-res);
}
// }}}
#line 13 "Math/tests/sqrt_mod.test.cpp"

int32_t main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int ntest; cin >> ntest;
    while (ntest--) {
        long long n, p; cin >> n >> p;
        long long res = sqrtMod(n, p);
        cout << res << '\n';
    }
    return 0;
}
Back to top page