Quadratic equation

Quadratic equation

牛客多校九B

给定

$(x+y)\%mod=b$

$(x*y)\%mod=c$

求 $x,y$

二次剩余

求$((x-y)^{2})\%mod = (b\times b-4\times c)\%mod$

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll qp(ll a, ll b, ll c)
{
    ll ans = 1;
    while (b)
    {
        if (b % 2 == 1)ans = (ans*a) % c;
        b /= 2;
        a = (a*a) % c;
    }
    return ans;
}

ll p=mod;
ll w;//二次域的D值
bool ok;//是否有解

struct QuadraticField//二次域
{
    ll x, y;
    QuadraticField operator*(QuadraticField T)//二次域乘法重载
    {
        QuadraticField ans;
        ans.x = (this->x*T.x%p + this->y*T.y%p*w%p) % p;
        ans.y = (this->x*T.y%p + this->y*T.x%p) % p;
        return ans;
    }
    QuadraticField operator^(ll b)//二次域快速幂
    {
        QuadraticField ans;
        QuadraticField a = *this;
        ans.x = 1;
        ans.y = 0;
        while (b)
        {
            if (b & 1)
            {
                ans = ans*a;
                b--;
            }
            b /= 2;
            a = a*a;
        }
        return ans;
    }
};

ll Legender(ll a)//求勒让德符号
{
    ll ans=qp(a, (p - 1) / 2, p);
    if (ans + 1 == p)//如果ans的值为-1,%p之后会变成p-1。
        return -1;
    else
        return ans;
}

ll Getw(ll n, ll a)//根据随机出来a的值确定对应w的值
{
    return ((a*a - n) % p + p) % p;//防爆处理
}

ll solve(ll n)
{
    ll a;
    if(n==0)
        return 0;
    if (p == 2)//当p为2的时候,n只会是0或1,然后0和1就是对应的解
        return n;
    if (Legender(n) == -1)//无解
        ok = false;
    srand((unsigned)time(NULL));
    while (1)//随机a的值直到有解
    {
        a = rand()%p;
        w = Getw(n, a);
        if (Legender(w) == -1)
            break;
    }
    QuadraticField ans,res;
    res.x = a;
    res.y = 1;//res的值就是a+根号w
    ans = res ^ ((p + 1) / 2);
    return ans.x;
}

int main()
{
    ll q;
    scanf("%lld",&q);
    ll a,b,n,ans1,ans2;
    ll inv2=qp(2,mod-2,mod);
    while (q--)
    {

        scanf("%lld%lld",&a,&b);

        ok = true;
        n=(a*a%mod-4*b%mod+mod)%mod;
        
        ans1 = solve(n);
      
        ans2 = p - ans1;//一组解的和是p
        if (!ok)
        {
            cout<<-1<<' '<<-1<<'\n';
        }
        else
        {
            ll x=(ans1+a)%p*inv2%p;
            ll y=(a-x+p)%p;
            printf("%lld %lld\n", min(x,y),max(x,y) );
        }
    }
}

 

posted @ 2019-08-15 18:03  liulex  阅读(436)  评论(0编辑  收藏  举报