B
一开始只知道二次剩余 不会求值
然后 x+y = n % p
那么 (x+y)^2 = n^2 %p
那么可以推出 (x-y)^2 = b^2 - 4*c %p
然后验算即可
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
using namespace std;
typedef long long LL;
LL quick_mod(LL a, LL b, LL m)
{
LL ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = ans * a % m;
b--;
}
b >>= 1;
a = a * a % m;
}
return ans;
}
struct T
{
LL p, d;
};
LL w;
//二次域乘法
T multi_er(T a, T b, LL m)
{
T ans;
ans.p = (a.p * b.p % m + a.d * b.d % m * w % m) % m;
ans.d = (a.p * b.d % m + a.d * b.p % m) % m;
return ans;
}
//二次域上快速幂
T power(T a, LL b, LL m)
{
T ans;
ans.p = 1;
ans.d = 0;
while(b)
{
if(b & 1)
{
ans = multi_er(ans, a, m);
b--;
}
b >>= 1;
a = multi_er(a, a, m);
}
return ans;
}
//求勒让德符号
LL Legendre(LL a, LL p)
{
return quick_mod(a, (p-1)>>1, p);
}
LL mod(LL a, LL m)
{
a %= m;
if(a < 0) a += m;
return a;
}
LL Solve(LL n,LL p)
{
if(n == 0) return 0;
if (Legendre(n, p) + 1 == p)
return -1;
LL a = -1, t;
while(true)
{
a = rand() % p;
t = a * a - n;
w = mod(t, p);
if(Legendre(w, p) + 1 == p) break;
}
T tmp;
tmp.p = a;
tmp.d = 1;
T ans = power(tmp, (p + 1)>>1, p);
return ans.p;
}
int main()
{
//freopen("B.txt","r",stdin);
//freopen("tmp.txt","w",stdout);
int t;
LL p = 1000000007;
scanf("%d", &t);
while(t--)
{
long long n,B,B_,C,C_,x,y;
scanf("%lld%lld",&B,&C);
n = B*B - 4*C;
n %= p;
long long a = Solve(n, p);
if(a == -1)
{
printf("-1 -1\n");
continue;
}
bool flag = false;
// long long b = p-a;
// if(a>b) swap(a,b);
long long b = a-p;
// cout <<" a = " << a-p << endl;
// cout << "b = " << b-p <<endl;
B_ = B;C_ = C;
if(b%2==0)
{
if(B%2==1)
{
B+=p;
}
y = ((B-b)/2)%p;
x = (y+b)%p;
x = (x+p)%p;
y = (y+p)%p;
if(x>y) swap(x,y);
if((x%p*y%p)%p==C)
{
printf("%lld %lld\n",x,y);
flag = true;
}
}
else
{
if(B%2==0)
{
B+=p;
}
y = ((B-b)/2)%p;
x = (y+b)%p;
x = (x+p)%p;
y = (y+p)%p;
if(x>y) swap(x,y);
if((x%p*y%p)%p==C)
{
printf("%lld %lld\n",x,y);
flag = true;
}
}
b = -a;
if(!flag)
{
B = B_ ;C = C_;
if(b%2==0)
{
if(B%2==1)
{
B+=p;
}
y = ((B-b)/2)%p;
x = (y+b)%p;
x = (x+p)%p;
y = (y+p)%p;
if(x>y) swap(x,y);
if((x%p*y%p)%p==C)
{
printf("%lld %lld\n",x,y);
flag = true;
}
}
else
{
if(B%2==0)
{
B+=p;
}
y = ((B-b)/2)%p;
x = (y+b)%p;
x = (x+p)%p;
y = (y+p)%p;
if(x>y) swap(x,y);
if((x%p*y%p)%p==C)
{
printf("%lld %lld\n",x,y);
flag = true;
}
}
}
if(!flag) printf("-1 -1\n");
}
return 0;
}