数论 二次剩余定理+模板

概念
偶质数:既是质数,又是偶数的数称为偶质数。(只有2)
奇质数:既是质数,又是奇数的数称为奇质数。(除了2以外的质数)

二次剩余定理
二次剩余定理能够解方程: x 2 = n ( m o d   p ) x^2 = n (mod\ p) x2=n(mod p) 其中p是一个奇质数。

二次剩余定理告诉我们,这个方程的解是 x = ( a + w ) p + 1 x= (a + \sqrt[]w )^{p + 1} x=(a+w )p+1

核心
判断是否有解核心有两点:一是利用费马小定理,二是构造平方差公式脑洞

证明过程
在这里插入图片描述在这里插入图片描述

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL w;
struct T{
    LL p, d;
};
LL quick_mod(LL a, LL b, LL m){//快速幂
    LL ans = 1;
    while(b){
        if(b & 1)
            ans = ans * a % m;
        a = a * a % m;
        b >>= 1;
    }
    return ans;
} 
T multi_er(T a, T b, LL m){//二次域乘法
    T ans;
    ans.p = (a.p * b.p % m + a.d * b.d % m * w % m) % m;
    ans.d = (a.p * b.d % m + a.d * b.p % m) % m;
    return ans;
}
T power(T a, LL b, LL m){//二次域上快速幂
    T ans;
    ans.p = 1;
    ans.d = 0;
    while(b){
        if(b & 1){
            ans = multi_er(ans, a, m);
            b--;
        }
        b >>= 1;
        a = multi_er(a, a, m);
    }
    return ans;
}
LL Legendre(LL a, LL p){//求勒让德符号
    return quick_mod(a, (p-1)>>1, p);
}
LL mod(LL a, LL m){
    a %= m;
    if(a < 0) a += m;
    return a;
}
LL Solve(LL n,LL p){
    if(p == 2) return 1;
    if (Legendre(n, p) + 1 == p)
        return -1;
    LL a = -1, t;
    while(true){
        a = rand() % p;
        t = a * a - n;
        w = mod(t, p);
        if(Legendre(w, p) + 1 == p) break;
    }
    T tmp;
    tmp.p = a;
    tmp.d = 1;
    T ans = power(tmp, (p + 1)>>1, p);
    return ans.p;
}
int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        LL n, p;//n是余数,p是mod
        scanf("%lld %lld", &n, &p);
        n %= p;
        LL a = Solve(n, p);
        if(a == -1)//x无解的情况
        {
            puts("No root");
            continue;
        }
        //有解的情况下
        LL b = p - a;
        if(a > b) 
            swap(a, b);
        if(a == b)//如果两个解相同,输出一个即可
            printf("%lld\n", a);
        else//如果两个解不同,分别输出(从小到大)
            printf("%lld %lld\n", a, b);
    }
    return 0;
}

参考来源

acmdreamer的博客,跟着推导完后还是很迷糊。这篇博文后面还讲了模数是Pn 的方程的求解。
https://blog.csdn.net/acdreamers/article/details/10182281

博客,这篇博客讲的很好很详细。
https://blog.csdn.net/a_crazy_czy/article/details/51959546

博客
https://blog.csdn.net/qq_33229466/article/details/79125057

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值