【模板】 二次剩余

求解
x 2 = n m o d    p x^2=n \mod p x2=nmodp
以及解一元二次方程

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

namespace QuadraticResidue {
    typedef long long ll;
    typedef pair<ll, ll> pll;

    ll qpow(ll a, ll b, ll m) {
        ll res = 1;
        a %= m;
        while (b) {
            if (b & 1) {
                res = res * a % m;
                b--;
            }
            b >>= 1;
            a = a * a % m;
        }
        return res;
    }


    ll w;

    //二次域乘法
    pll multi_er(pll a, pll b, ll m) {
        pll res;
        res.first = (a.first * b.first % m + a.second * b.second % m * w % m) % m;
        res.second = (a.first * b.second % m + a.second * b.first % m) % m;
        return res;
    }

    //二次域上快速幂
    pll QR_qpow(pll a, ll b, ll m) {
        pll res;
        res.first = 1;
        res.second = 0;
        while (b) {
            if (b & 1) {
                res = multi_er(res, a, m);
                b--;
            }
            b >>= 1;
            a = multi_er(a, a, m);
        }
        return res;
    }

    //求勒让德符号
    ll Legendre(ll a, ll p) {
        return qpow(a, (p - 1) >> 1, p);
    }

    ll Mod(ll a, ll m) {
        a %= m;
        if (a < 0) a += m;
        return a;
    }

    //二次剩余板子 求解 x^2=n mod p
    // 返回其中的一个解 x0 另一个解 x1= p-x0
    ll QR(ll n, ll p) {
        n %= p;

        if (n == 0) return 0;
        if (p == 2) return 1;
        if (Legendre(n, p) + 1 == p)
            return -1;
        ll x0 = -1, t;
        while (true) {
            x0 = rand() % p;
            t = x0 * x0 - n;
            w = Mod(t, p);
            if (Legendre(w, p) + 1 == p) break;
        }
        pll tmp;
        tmp.first = x0;
        tmp.second = 1;
        pll res = QR_qpow(tmp, (p + 1) >> 1, p);
        return res.first;

    }
}
using namespace QuadraticResidue;


int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        int n, p;
        scanf("%d %d", &n, &p);

        int a = QR(n, p);
        if (a == -1) {
            // 无解
            continue;
        }
        int b = p - a;//另一个解
        if (a > b) swap(a, b);
        if (a == b)
            printf("%d\n", a);
        else
            printf("%d %d\n", a, b);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值