题意:
x + y = b(mod p)
x * y = c(mod p)
题目给出b,c ,p = 1e9 + 7,求解x y 要求(0≤x≤y<p),若没有可行解,输出-1 -1
题解:
x + y = b(mod p) 可得 (x + y) ^ 2 = (b * b)(mod p). 再可得 x ^ 2 - 2 * x * y + y ^ 2 = (b * b mod p - 4 * c mod p + p ) (mod p),即二次剩余求解
考虑 x = y时 b ^ 2 - 4 * c = 0的细节
求出 |x - y| 的解为 X 或 p - X 的话,由于y >= x,所以 y - x = X 或 y - x = p - X,考虑x + y 为 b 和 p + b两种情况分别判断是否满足 0 <= x <= y < p 即可,不满足输出 -1 -1
ps:金老板太厉害了,这种题目以后不可以陷到化简代换之中,应把握整体,构造恒等式求解
#include<cstdio>
using namespace std;
const long long mod = 1e9 + 7;
#define LL long long
LL B,C;
LL Pow(LL a,LL b,LL p) {
LL res = 1;
for (; b; a = 1LL * a * a % p, b >>= 1)
if (b & 1) res = 1LL * a * res % p;
return res;
}
bool Legendre(LL a,LL p) {
return Pow(a, p - 1 >> 1, p) == 1;
}
bool check(LL b,LL x) {
if ((b + x) % 2 == 1)
return false;
LL xx = (x + b) / 2;
LL yy = (b - x) / 2;
if (0 <= xx && xx < mod && 0 <= yy && yy < mod)
return true;
return false;
}
void modsqr(LL a,LL p) {
LL x;
LL i, k, b;
if (p == 2) x = a % p;
else if (p % 4 == 3) x = Pow(a, p + 1 >> 2, p);
else {
for (b = 1; Legendre(b, p); ++b);
i = p - 1 >> 1;
k = 0;
do {
i >>= 1;
k >>= 1;
if (!((1LL * Pow(a, i, p) * Pow(b, k, p) + 1) % p)) k += p - 1 >> 1;
} while (!(i & 1));
x = 1LL * Pow(a, i + 1 >> 1, p) * Pow(b, k >> 1, p) % p;
}
if (p - x < x) x = p - x;
if (x == p - x) {
if (check(B, x))
printf("%lld %lld\n", (B - x) / 2, (B + x) / 2);
else if (check(B + p, x))
printf("%lld %lld\n", (B + p - x) / 2, 1LL * (B + p + x) / 2);
else puts("-1 -1");
} else {
if (check(B, x)) printf("%lld %lld\n", (B - x) / 2, (B + x) / 2);
else if (check(B, p - x)) printf("%lld %lld\n", (B - p + x) / 2, (B - x + p) / 2);
else if (check(B + p, x)) printf("%lld %lld\n", (B - x + p) / 2, (B + x + p) / 2);
else if (check(B + p, p - x)) printf("%lld %lld\n", (B + x) / 2, (B - x + 2 * p) / 2);
else puts("-1 -1");
}
}
int main() {
int T;
scanf("%d", &T);
LL a;
while (T--) {
scanf("%lld %lld", &B, &C);
a = (B * B % mod - 4LL * C % mod + mod);
a %= mod;
if (a == 0) {
if (B % 2 == 0) printf("%lld %lld\n", B / 2, B / 2);
else printf("%lld %lld\n", (B + mod) / 2, (B + mod) / 2);
continue;
}
if (!Legendre(a, mod)) {
puts("-1 -1");
continue;
}
modsqr(a, mod);
}
return 0;
}