求解
x
2
=
n
m
o
d
p
x^2=n \mod p
x2=nmodp
以及解一元二次方程
#include <bits/stdc++.h>
using namespace std;
namespace QuadraticResidue {
typedef long long ll;
typedef pair<ll, ll> pll;
ll qpow(ll a, ll b, ll m) {
ll res = 1;
a %= m;
while (b) {
if (b & 1) {
res = res * a % m;
b--;
}
b >>= 1;
a = a * a % m;
}
return res;
}
ll w;
//二次域乘法
pll multi_er(pll a, pll b, ll m) {
pll res;
res.first = (a.first * b.first % m + a.second * b.second % m * w % m) % m;
res.second = (a.first * b.second % m + a.second * b.first % m) % m;
return res;
}
//二次域上快速幂
pll QR_qpow(pll a, ll b, ll m) {
pll res;
res.first = 1;
res.second = 0;
while (b) {
if (b & 1) {
res = multi_er(res, a, m);
b--;
}
b >>= 1;
a = multi_er(a, a, m);
}
return res;
}
//求勒让德符号
ll Legendre(ll a, ll p) {
return qpow(a, (p - 1) >> 1, p);
}
ll Mod(ll a, ll m) {
a %= m;
if (a < 0) a += m;
return a;
}
//二次剩余板子 求解 x^2=n mod p
// 返回其中的一个解 x0 另一个解 x1= p-x0
ll QR(ll n, ll p) {
n %= p;
if (n == 0) return 0;
if (p == 2) return 1;
if (Legendre(n, p) + 1 == p)
return -1;
ll x0 = -1, t;
while (true) {
x0 = rand() % p;
t = x0 * x0 - n;
w = Mod(t, p);
if (Legendre(w, p) + 1 == p) break;
}
pll tmp;
tmp.first = x0;
tmp.second = 1;
pll res = QR_qpow(tmp, (p + 1) >> 1, p);
return res.first;
}
}
using namespace QuadraticResidue;
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, p;
scanf("%d %d", &n, &p);
int a = QR(n, p);
if (a == -1) {
// 无解
continue;
}
int b = p - a;//另一个解
if (a > b) swap(a, b);
if (a == b)
printf("%d\n", a);
else
printf("%d %d\n", a, b);
}
return 0;
}