链接:https://ac.nowcoder.com/acm/contest/889/B
来源:牛客网
题目描述
Amy asks Mr. B problem B. Please help Mr. B to solve the following problem.
Let p = 1000000007.
Given two integers b and c, please find two integers x and y(0 \leq x \leq y < p)(0≤x≤y<p), such that
(x + y) \bmod p = b(x+y)modp=b
(x \times y) \bmod p = c(x×y)modp=c
输入描述:
The first line contains an integer t, which is the number of test cases (1 <= t <= 10).
In the following t lines, each line contains two integers b and c (0 <= b, c < p).
输出描述:
For each test case, please output x, y in one line.
If there is a solution, because x <= y, the solution is unique.
If there is no solution, please output -1, -1
示例1
输入
复制
10
4 4
5 6
10 10
10 25
20000 100000000
0 5
3 6
220 284
0 1
1000000000 1000000000
输出
复制
2 2
2 3
-1 -1
5 5
10000 10000
474848249 525151758
352077071 647922939
448762649 551237578
-1 -1
366417496 633582504
题目大意:
给定一个b,c,p (0<b,c<p)
(x+y)%p = b
(x*y)%p = c
求x y (0 x <=y<p )
解题思路:
首先得知道 二次同余方程
x² mod p == n 知道p和n是可以解出x的
(x-y)² mod p = (x+y)² mod p - 4*(xy)mod p
因为 (x+y)%p = b (xy)%p = c
所以 (x-y)² mod p = (b^2 - 4c + 4p)mod p
所以 (x-y)² 和 b^2 - 4*c 同余 关于p
由: x² mod p == n
我们令 x = (x-y) 令n = (b^2 - 4c + 4p)mod p;
通过模板,这样我们就可以 解出 x-y = ? 设为 a。解有两个 a 和 p-a
因为 x,y<p 所以 x+y<2p
因为(x+y)%p = b 所以 x+y = b或者 x+y = b+p;
由上面解出的 x-y = a 加上 x+y = b||b+p 就能解出 x和y了。
需要注意的是,当 b^2-4*c==0时,这是 x-y 和 0同余 ,那么x-y = 0 即x=y 这个需要特判一下。
然后就是分类讨论各种情况了
x+y = b x-y = a
x+y = b x- y = p -a
x+y = b+p x-y = a
x+y = b+p x-y = p-a
AC代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll p = 1000000007;
ll qpow(ll a,ll b,ll p){
ll ans=1;
while(b){
if(b&1) ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
ll modsqr(ll a,ll n){
ll b,k,i,x;
if(n==2) return a%n;
if(qpow(a,(n-1)/2,n) == 1){
if(n%4 == 3){
x=qpow(a,(n+1)/4,n);
}
else{
for(b=1; qpow(b,(n-1)/2,n) == 1; b++);
i = (n-1)/2;
k=0;
while(i%2==0){
i /= 2,k /= 2;
if((qpow(a,i,n)*qpow(b,k,n)+1)%n == 0) k += (n-1)/2;
}
x = qpow(a,(i+1)/2,n)*qpow(b,k/2,n)%n;
}
if(x*2 > n) x = n-x;
return x;
}
return -1;
}
int main()
{
int t;
scanf("%d", &t);
ll b,c;
while(t--){
scanf("%lld%lld",&b,&c);
ll n = (b*b%p - (4*c)%p+4*p)%p;
ll a = modsqr(n,p);
if(b*b - 4*c == 0) a = 0;
if(a == -1){
cout<<"-1 -1"<<endl;
continue;
}
ll x,y;
int flag = 0;
for(ll i=0;i<=1;i++){
if((i*p+b-a)%2==0){
y = (i*p+b-a)/2;
x = a+y;
if(x>y) swap(x,y);
if(x>=0&&x<p&&y>=0&&y<p){
flag = 1;
break;
}
}
}
if(flag) cout<<x<<" "<<y<<endl;
else{
a = p - a;
for(ll i=0;i<=1;i++){
if((i*p+b-a)%2==0){
y = (i*p+b-a)/2;
x = a+y;
if(x>y) swap(x,y);
if(x>=0&&x<p&&y>=0&&y<p){
flag = 1;
break;
}
}
}
if(!flag) cout<<"-1 -1"<<endl;
else cout<<x<<" "<<y<<endl;
}
}
return 0;
}