题意
{
(
x
+
y
)
m
o
d
  
p
=
b
x
∗
y
m
o
d
  
p
=
c
\begin{cases} (x+y)\mod p = b\\ x*y\mod p = c\\ \end{cases}
{(x+y)modp=bx∗ymodp=c
求解 x , y x,y x,y
思路
不考虑取模的情况下,原式可以化成
b
2
−
4
∗
c
=
(
x
−
y
)
2
b^2-4*c = (x-y)^2
b2−4∗c=(x−y)2
在取模的意义下用二次剩余求
x
−
y
x-y
x−y 的解
r
e
s
res
res,最后联立
x
+
y
=
b
x+y=b
x+y=b
求出解
x
,
y
x,y
x,y后判断是否成立即可
#include <iostream>
#include <ctime>
using namespace std;
typedef long long LL;
#define random(a,b) (rand()%(b-a+1)+a)
const LL mod = 1e9+7;
LL p = mod;
LL w;//二次域的D值
bool ok;//是否有解
LL quick_mod(LL a, LL b, LL c) { LL ans = 1; while (b) { if (b % 2 == 1)ans = (ans*a) % c; b /= 2; a = (a*a) % c; }return ans; }
struct QuadraticField//二次域
{
LL x, y;
QuadraticField operator*(QuadraticField T)//二次域乘法重载
{
QuadraticField ans;
ans.x = (this->x*T.x%p + this->y*T.y%p*w%p) % p;
ans.y = (this->x*T.y%p + this->y*T.x%p) % p;
return ans;
}
QuadraticField operator^(LL b)//二次域快速幂
{
QuadraticField ans;
QuadraticField a = *this;
ans.x = 1;
ans.y = 0;
while (b)
{
if (b & 1)
{
ans = ans*a;
b--;
}
b /= 2;
a = a*a;
}
return ans;
}
};
LL Legender(LL a)//求勒让德符号
{
LL ans=quick_mod(a, (p - 1) / 2, p);
if (ans + 1 == p)//如果ans的值为-1,%p之后会变成p-1。
return -1;
else
return ans;
}
LL Getw(LL n, LL a)//根据随机出来a的值确定对应w的值
{
return ((a*a - n) % p + p) % p;//防爆处理
}
LL Solve(LL n)
{
LL a;
if (p == 2)//当p为2的时候,n只会是0或1,然后0和1就是对应的解
return n;
if (Legender(n) == -1)//无解
ok = false;
srand((unsigned)time(NULL));
while (1)//随机a的值直到有解
{
a = random(0, p - 1);
w = Getw(n, a);
if (Legender(w) == -1)
break;
}
QuadraticField ans,res;
res.x = a;
res.y = 1;//res的值就是a+根号w
ans = res ^ ((p + 1) / 2);
return ans.x;
}
LL quick(LL a,LL b){
LL res = 1;
while(b){
if(b&1) res = res*a%mod;
b >>= 1;
a = a*a%mod;
}
return res;
}
int main(){
LL inv2 = quick(2LL,mod-2);
int T;
scanf("%d",&T);
while(T--){
LL b,c;
scanf("%lld%lld",&b,&c);
ok = true;
//ll cb = b, cc = c;
LL tmp = (b*b-4*c+mod)%mod;
if(tmp == 0){
printf("%lld %lld\n",b*inv2%mod,b*inv2%mod);
continue;
}
LL ans = Solve(tmp);
LL ans1 = tmp-ans;
if(!ok){
puts("-1 -1");
}else{
int f = 0;
if(!f){
LL x = (b+ans)*inv2%mod;
LL y = (b-ans+mod)*inv2%mod;
if((x+y)%mod == b && (x*y)%mod == c){
if(x > y) swap(x,y);
f = 1;
printf("%lld %lld\n",x,y);
}
}
if(!f) puts("-1 -1");
}
}
}