B Quadratic equation
题意
在模p=1e9+7意义下
(
x
+
y
)
m
o
d
p
=
b
(x+y)modp= b
(x+y)modp=b
(
x
×
y
)
m
o
d
p
=
c
(x×y)modp=c
(x×y)modp=c
求x,y,无解则输出-1 -1
题解
学到了新东西,二次剩余。求的是
x
2
≡
a
(
m
o
d
p
)
x^2\equiv a(mod p)
x2≡a(modp)的解x,乍一看和这题没啥关系。实际上这题不论怎么转化最终都还是要求这个x。
首先原式子可以化成
(
x
+
y
)
2
−
4
×
(
x
×
y
)
≡
b
2
−
4
c
(x+y)^2-4×(x×y)\equiv b^2-4c
(x+y)2−4×(x×y)≡b2−4c
然后就变为了
(
x
−
y
)
2
≡
b
2
−
4
c
(x-y)^2\equiv b^2-4c
(x−y)2≡b2−4c
然后就是套二次剩余的板子求出x-y,再联立x+y求出x,y。
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
ll b, c;
ll mod = 1e9 + 7;
ll w, n;
struct Complex //复数
{
ll x, y;
Complex(ll _x = 0, ll _y = 0)
{
x = _x;
y = _y;
}
};
Complex operator*(Complex a, Complex b) //复数乘
{
return Complex((a.x * b.x % mod + a.y * b.y % mod * w % mod) % mod, (a.x * b.y + a.y * b.x) % mod);
}
ll qpow(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
Complex qpow(Complex a, ll y)
{
Complex ans = Complex(1, 0);
while (y)
{
if (y & 1)
ans = ans * a;
a = a * a;
y >>= 1;
}
return ans;
}
ll Legendre(ll x,ll mod)
{
return qpow(x, (mod - 1) >> 1);
}
int slove(ll n,ll mod) //返回值为其中一个解,另一个解为mod-返回值
{
if(n==0)
return 0;
if(n==1)
return 1;
if(Legendre(n,mod)+1==mod)
return -1; //非二次剩余,在mod下无法开方
ll a, temp;
while(1)
{
a = rand() % mod;
temp=a*a-n;
w=(temp%mod+mod)%mod;
if(Legendre(w,mod)+1==mod) break;
}
Complex te;
te.x=a;
te.y=1;
Complex ans=qpow(te,(mod+1)>>1);
return ans.x;
}
int main()
{
srand(time(0));
int t;
scanf("%d", &t);
while (t--)
{
scanf("%lld%lld", &b, &c);
n = b * b % mod - 4 * c % mod + mod;
n %= mod;
ll a = slove(n, mod);
if(a==-1)
printf("-1 -1\n");
else {
ll x = (a + b) * qpow(2, mod - 2)%mod;
ll y = (b - a + mod) * qpow(2, mod - 2) % mod;
if(x>y)
swap(x, y);
printf("%lld %lld\n", x, y);
}
}
}