Live2d Test Env

2019牛客暑期多校训练营(第九场)B:Quadratic equation (二次剩余求mod意义下二元一次方程)

题意:给定p=1e9+7,A,B。  求一对X,Y,满足(X+Y)%P=A; 且(X*Y)%P=B;

思路:即,X^2-BX+CΞ0;  那么X=[B+-sqrt(B^2-4C)]/2;

全部部分都要在modP意义下,所以求一个x满足x^2%p=B^2-4C,这个用二次剩余求即可。

套了模板。

#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
typedef long long ll;
int k; ll a,p,w;
struct T{ll x,y;};
T mul_two(T a,T b,ll p)
{
    T 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;
}
T qpow_two(T a,ll n,ll p)
{
    T ans; ans.x=1; ans.y=0;
    while(n){
        if(n&1) ans=mul_two(ans,a,p);
        n>>=1;
        a=mul_two(a,a,p);
    }
    return ans;
}
ll qpow(ll a,ll n,ll p)
{
    ll ans=1; a%=p;
    while(n){
        if(n&1) ans=ans*a%p;
        n>>=1;a=a*a%p;
    }
    return ans%p;
}
ll Legendre(ll a,ll p)
{
    return qpow(a,(p-1)>>1,p);
}
int solve(ll n,ll p)
{
    n%=p; if(p==2) return 1;
    if(Legendre(n,p)+1==p) return -1;
    else if(n==0) return 0;
    ll a=1;
    while(Legendre((a*a-n+p)%p,p)+1!=p)  a=rand()%p;
    T tmp; tmp.x=a; tmp.y=1; w=(a*a-n+p)%p;//W
    T ans=qpow_two(tmp,(p+1)>>1,p);
    return ans.x;
}
int main()
{
    scanf("%d",&k); ll rev2=500000004;
    while(k--){
        ll b,c;
        scanf("%lld%lld",&b,&c);
        ll t=((b*b-c*4)%mod+mod)%mod;
        ll d=solve(t,mod);
        if(d==-1){
            printf("-1 -1\n");
            continue;
        }
        ll x=(b+d)*rev2%mod,y=(b-x+mod)%mod;
        if(x>y) swap(x,y);
        printf("%lld %lld\n",x,y);
    }
    return 0;
}

 

posted @ 2019-08-15 23:23  nimphy  阅读(377)  评论(0编辑  收藏  举报