zoukankan      html  css  js  c++  java
  • 除法取模与逆元/费马小定理

    对于正整数,如果有,那么把这个同余方程中的最小正整数解叫做的逆元。

    逆元一般用扩展欧几里得算法来求得,如果为素数,那么还可以根据费马小定理得到逆元为。(都要求a和m互质)

    推导过程如下(摘自Acdreamer博客)

    这个为费马小定理,m为素数是费马小定理的前置条件。

    求a/b=x(mod M)

    只要M是一个素数,而且b不是M的倍数,就可以用一个逆元整数b1,通过 a/b=a*b1 (mod M),只能来以乘换除。
    费马小定理:对于素数 M 任意不是 M 的倍数的 b,都有:b ^ (M-1) = 1 (mod M)
    于是可以拆成:b*b^(M-2)=1(mod M)
    于是:a/b=a/b*(b * b ^ (M-2))=a*(b ^ (M-2)) (mod M)

    求a/b=x(mod M)

    用扩展欧几里德算法算出b1,然后计算a*b1(mod M)

    exgcd(b,M,x,y);   b1=x;

     

    当p是个质数的时候有
    inv(a) = (p - p / a) * inv(p % a) % p

     

    证明:

    设x = p % a,y = p / a
    于是有 x + y * a = p
    (x + y * a) % p = 0
    移项得 x % p = (-y) * a % p
    x * inv(a) % p = (-y) % p
    inv(a) = (p - y) * inv(x) % p
    于是 inv(a) = (p - p / a) * inv(p % a) % p

    然后一直递归到1为止,因为1的逆元就是1

     1 #include<cstdio>
     2 typedef long long LL;
     3 LL inv(LL t, LL p) 
     4 {//求t关于p的逆元,注意:t要小于p,最好传参前先把t%p一下 
     5     return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p;
     6 }
     7 int main()
     8 {
     9     LL a, p;
    10     while(~scanf("%lld%lld", &a, &p))
    11     {
    12         printf("%lld
    ", inv(a%p, p));
    13     }
    14 }

    它可以在O(n)的复杂度内算出n个数的逆元

     1 #include<cstdio>
     2 const int N = 200000 + 5;
     3 const int MOD = (int)1e9 + 7;
     4 int inv[N];
     5 int init()
     6 {
     7     inv[1] = 1;
     8     for(int i = 2; i < N; i ++)
     9         inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
    10 }
    11 int main()
    12 {
    13     init();
    14 }
  • 相关阅读:
    kafka学习笔记(六)kafka的controller模块
    腾讯蓝鲸使用笔记
    kafka学习笔记(五)kafka的请求处理模块
    kafka学习笔记(四)kafka的日志模块
    kafka学习笔记(三)kafka的使用技巧
    kafka学习笔记(二)kafka的基本使用
    kafka学习笔记(一)消息队列和kafka入门
    大数据安全与RANGER学习和使用
    10-Linux 基本指令
    09-迭代器、模块
  • 原文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/6847672.html
Copyright © 2011-2022 走看看