链接:https://ac.nowcoder.com/acm/contest/889/B
来源:牛客网
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
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≤x≤y
(x+y) mod p=b(x + y) \bmod p = b(x+y)modp=b
(x×y) mod p=c(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
题意:就是求满足(x+y)%p=b,(x*y)%p=c,0<=x<=y
题解:我们知道x+y,怎样求x和y呢,想到求出x-y这样就可以求出x,y来了,知道(x-y)^2=(x+y)^2-4xy=(b^2-4c)%p,为什么呢?因为0<=x
上代码:
#include
#include
#include
using namespace std;
typedef long long ll;
const int p=1e9+7;
struct hh{
ll x,y;
hh(){};
hh(ll _x,ll _y){
x=_x;y=_y;
}
};
ll w;
hh mul(hh a,hh b,ll p){
hh 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;
}
hh quick1(hh a,ll b,ll p){
hh ans=hh(1,0);
while(b){
if(b&1) ans=mul(ans,a,p);
a=mul(a,a,p);
b>>=1;
}
return ans;
}
ll quick2(ll a,ll b,ll p){
ll ans=1;
while(b){
if(b&1) ans=(ans*a)%p;
b>>=1;
a=(a*a)%p;
}
return ans;
}
ll solve(ll a,ll p){//求解 x^2=a(mod p) 的x的值
a%=p;//注意这句话
if(a==0) return 0;//注意这句话
if(p==2) return a;
if(quick2(a,(p-1)/2,p)==p-1) return -1;
ll b,t;
while(1){
b=rand()%p;
t=b*b-a;
w=(t%p+p)%p;
if(quick2(w,(p-1)/2,p)==p-1) break;
}
hh ans=hh(b,1);
ans=quick1(ans,(p+1)/2,p);
return ans.x;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
ll b,c;
scanf("%lld%lld",&b,&c);
ll cao=solve(b*b-4*c+p,p);
if(cao==-1) puts("-1 -1");
else{
ll w=(b+cao)%p*quick2(2ll,p-2,p);
w%=p;
ll ww=(b-w+p)%p;
if(w>ww) swap(w,ww);//注意先输出小的,再输出大的
printf("%lld %lld\n",w,ww);
}
}
return 0;
}