数论 扩欧 逆元 中国剩余定理 (转)

本文介绍了同余的概念及其在数论中的应用,包括费马小定理、逆元的求解方法及中国剩余定理等内容,并提供了相关算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

同余的意义

12 三等号 5(mod 7)

12 和 5 在除数相同时 余数相同

a  b(mod ) c

m n (mod) c

a+m  b+n (mod) c

(a(+||*)b)%c = (a%c+b%c)%c

(a-b)%c=((a%c-b%c)+c)%c

逆元:a×b=1(单位元)a,b互为逆元 

幺元:代数系统中的度量 1×a=a 乘相当于没有乘

11 : 一个数对11求余 奇数位数减去,偶数位数加上

a(n)*10(n)+a(n-1)*10(n-1)

10 的 n次方 (11-1)(n个)%10相乘

费马小定理:(a的p-1次幂  对p求余) 等于 (1对p求余)(a和p互为素数)

贝祖等式:ax+by=gcd(a,b)=gcd(b,a%b);能写成这个 就有整数解

ax1+by1=bx2+(a%b)y2

ax1+by1=ay2+b(x2-(a/b)*y2)

x1=y2;

y1=x2-(a/b)*y2;

a|b 即为 a能整除 b

 

 

 

 

费马小定理

a^(p-1) ≡1 (mod p)

两边同除以a

a^(p-2) ≡1/a (mod p)

什么(,,• ₃ •,,),这可是数论,还敢写1/a

应该写a^(p-2) ≡ inv(a) (mod p)

 

所以inv(a) = a^(p-2) (mod p)

这个用快速幂求一下,复杂度O(logn)(ง •̀_•́)ง

LL pow_mod(LL a, LL b, LL p){//a的b次方求余p
    LL ret = 1;
    while(b){
        if(b & 1) ret = (ret * a) % p;
        a = (a * a) % p;
        b >>= 1;
    }
    return ret;
}
LL Fermat(LL a, LL p){//费马求a关于b的逆元
        return pow_mod(a, p-2, p);
}

 

方法二:

 

要用扩展欧几里德算法

还记得扩展欧几里德吗?(不记得的话,欧几里得会伤心的(╭ ̄3 ̄)╭♡)

 

a*x + b*y = 1

如果ab互质,有解

 

这个解的x就是a关于b的逆元

y就是b关于a的逆元

为什么呢?

 

你看,两边同时求余b

 

a*x % b + b*y % b = 1 % b

a*x % b = 1 % b

a*x = 1 (mod b)

 

你看你看,出现了!!!(/≥▽≤/)

所以x是a关于b的逆元

反之可证明y

 

附上代码:

#include<cstdio>
typedef long long LL;
void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
    if (!b) {d = a, x = 1, y = 0;}
    else{
        ex_gcd(b, a % b, y, x, d);
        y -= x * (a / b);
    }
}
LL inv(LL t, LL p){//如果不存在,返回-1
    LL d, x, y;
    ex_gcd(t, p, x, y, d);
    return d == 1 ? (x % p + p) % p : -1;
}
int main(){
    LL a, p;
    while(~scanf("%lld%lld", &a, &p)){
        printf("%lld\n", inv(a, p));
    }
}

 

 

二:中国剩余定理:

模板:

#include<stdio.h>
#include <iostream>
using namespace std;
//扩展欧几里得算法
int exgcd(int a,int b,int &x,int &y)
{
    int d;
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
 //中国剩余定理 ,r[]存放余数 ,prime[]存放两两互质的数
int Chinese_Remainder(int r[],int prime[],int len)
{
    int i,d,x,y,m,n=1,sum=0;
    //计算所以除数的积n,也是所以除数的最小公倍数
    for(i=0;i<len;i++)
        n*=prime[i];
    //计算符合所以条件的数
    for(i=0;i<len;i++)
    {
        m=n/prime[i];//计算除去本身的所有除数的积m
        d=exgcd(prime[i],m,x,y);//计算w[i]*x+m*y=gcd(w[i],m)的一个解y
        //累加整数解y的同并不断对n取余,其利用公式:(a+b)%c=(a%c+b%c)%c
        sum=(sum+y*m*r[i])%n;
    }
    return (n+sum%n)%n;//满足所以方程的最小解
}
int main()
{
    int n,i;
    int prime[15],r[15];
    while (printf("请输入组数n:\n"),scanf("%d",&n)!=EOF)
    {
        printf("请依次输入每组的除数和余数:\n");
        for (i=0;i<n;i++)
        {
            scanf("%d%d",&prime[i],&r[i]);
        }
        //printf("%d\n",Chinese_Remainder(b,w,n));
        printf("符合条件的最小整数:%d\n\n",Chinese_Remainder(r,prime,n));
    }
    return 0;
}

 

1.满足两两互质关系

LL china(int n, LL *a, LL *m)
{
    LL M = 1, ret = 0;
    for(int i = 0; i < n; i ++) M *= m[i];
    for(int i = 0; i < n; i ++)
    {
        LL w = M / m[i];
        ret = (ret + w * inv(w, m[i]) * a[i]) % M;
    }
    return (ret + M) % M;
}
2  不满足两两互质关系

typedef long long LL;
typedef pair<LL, LL> PLL;
PLL linear(LL A[], LL B[], LL M[], int n)  //求解A[i]x = B[i] (mod M[i]),总共n个线性方程组
{
    LL x = 0, m = 1;
    for(int i = 0; i < n; i ++)
    {
        LL a = A[i] * m, b = B[i] - A[i]*x, d = gcd(M[i], a);
        if(b % d != 0)  return PLL(0, -1);//答案不存在,返回-1
        LL t = b/d * inv(a/d, M[i]/d)%(M[i]/d);
        x = x + m*t;
        m *= M[i]/d;
    }
    x = (x % m + m ) % m;
    return PLL(x, m);//返回的x就是答案,m是最后的lcm值
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值