2019牛客暑期多校训练营(第九场)B——Quadratic equation(二次剩余)

链接: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<p)(0 \leq x \leq y < p)(0≤x≤y<p), such that

(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<p,的x,y的值

题解:我们知道x+y,怎样求x和y呢,想到求出x-y这样就可以求出x,y来了,知道(x-y)^2=(x+y)^2-4xy=(b^2-4c)%p,为什么呢?因为0<=x<p,0<=y<p,所以0<=x+y<2p,所以x+y=b或者b+p,结果就显然了,带进去即可,因为取模,所以带进b和b+p是一样的,这样我们利用二次剩余就求出x-y来了,当然由于取模所以求出的两个值对最终结果是一样的,这样我们就可以写代码了,注意一下细节就可以了~~

上代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
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;
}
发布了195 篇原创文章 · 获赞 27 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/lgz0921/article/details/99675633
今日推荐