2019牛客暑期多校训练营(第九场)Quadratic equation——二次剩余(模奇素数)&&Cipolla算法

题意

给定模 $p = 1000000007$ 和 $b,c$,求 $x$ 和 $y$($0\leq x\leq y< p$),其中 $x$ 和 $y$ 满足,

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

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

分析

根据模的性质,可化成 $(2x-b)^2 \equiv b^2-4c(mod \ p)$,然后核心问题是解 $x^2 \equiv a(mod\ p)$ 这个方程,直接上模板吧。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll p=1e9+7;
const ll inv2 = 500000004;
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的值,无解返回-1
    a = (a%p + p)%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;
}

ll b, c;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld%lld", &b, &c);
        ll two = solve(b*b-4*c, p);
        if(two == -1)  printf("-1 -1\n");
        else
        {
            ll x = (b+two) * inv2 % p;
            ll y = (b-x+p) % p;
            if(x > y)  swap(x, y);
            printf("%lld %lld\n", x, y);
        }
    }
    return 0;
}

 

 

 

参考链接:https://blog.csdn.net/lgz0921/article/details/99675633

posted @ 2019-08-16 15:32  Rogn  阅读(287)  评论(0编辑  收藏  举报