题意
p = 1000000007.
(x + y) % p = b
(x * y) % p = c
输入 b, c ,求 x,y,如果无解,输出-1 -1;
题意:
求(x+y)² = b² (x - y)² = b² - 4 * c
因为有模p, 所以求 (b² - 4*c) 对p的二次剩余(意思为在短时间内求出x-y的值)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int k;
ll a,b,c,w;
ll p = 1000000007;
struct T{
ll x,y;
};
T mul_two(T a,T b,ll p){
T ans;
ans.x=(a.x*b.x%p+a.y*b.y%p*w%p)%p;
ans.y=(a.x*b.y%p+a.y*b.x%p)%p;
return ans;
}
T qpow_two(T a,ll n,ll p){
T ans;
ans.x=1;
ans.y=0;
while(n){
if(n&1) ans=mul_two(ans,a,p);
n>>=1;
a=mul_two(a,a,p);
}
return ans;
}
ll qpow(ll a,ll n,ll p){
ll ans=1;
a%=p;
while(n){
if(n&1) ans=ans*a%p;
n>>=1;
a=a*a%p;
}
return ans%p;
}
ll Legendre(ll a,ll p){
return qpow(a,(p-1)>>1,p);
}
int solve(ll n,ll p){
if(p==2) return 1;
if(Legendre(n,p)+1==p) return -1;
ll a,t;
while(1){
a=rand()%p;
t=a*a-n;
w=(t%p+p)%p;
if(Legendre(w,p)+1==p) break;
}
T tmp;
tmp.x=a;
tmp.y=1;
T ans=qpow_two(tmp,(p+1)>>1,p);
return ans.x;
}
ll quick_pow(ll y){
int b = p - 2;
ll ans = 1;
while(b){
if(b % 2 == 1)
ans = (ans * y) % p;
y = (y * y )%p;
b /= 2;
}
return ans % p;
}
int main(){
scanf("%d",&k);
while(k--){
scanf("%lld%lld",&b,&c);
a = (b*b%p-4*c) %p;
if(a == 0){ // 当x == y 直接判断
if(b/2 * b/2 == c){
cout << b/2 << " " << b/2 << endl;
}
else{
cout << -1 << " " << -1 << endl;
}
continue;
}
a = (a + p) % p;
ll d = solve(a,p);
if(d == -1){ // 二次剩余为-1 时,无解
printf("-1 -1\n");
continue;
}
ll x = (b+d+p)%p*quick_pow(2); // 因为除二,所以对2取逆元
x = x % p;
ll y = (b - x+p)%p;
printf("%lld %lld\n",min(x, y),max(x, y));
}
return 0;
}