当前位置: 首页 > news >正文

Modular Multiplicative Inverse(模乘逆元)

计算模乘逆元原理上有四种方法:

1.暴力算法

2.扩展欧几里得算法

3.费尔马小定理

4.欧拉定理

模乘逆元定义:满足 ab≡1(mod m),称b为a模乘逆元。以下是有关概念以及四种方法及程序。

文章出处:Modular Multiplicative Inverse

The modular multiplicative inverse of an integer a modulo m is an integer x such thata^{-1} \equiv x \pmod{m}.

That is, it is the multiplicative inverse in the ring of integers modulo m. This is equivalent toax \equiv aa^{-1} \equiv 1 \pmod{m}.

1. Brute Force
We can calculate the inverse using a brute force approach where we multiply a with all possible valuesx and find ax such thatax \equiv 1 \pmod{m}. Here’s a sample C++ code:

int modInverse(int a, int m) {
    a %= m;
    for(int x = 1; x < m; x++) {
        if((a*x) % m == 1) return x;
    }
}

2. Using Extended Euclidean Algorithm
We have to find a number x such that a·x = 1 (mod m). This can be written as well as a·x = 1 + m·y, which rearranges into a·x – m·y = 1. Since x and y need not be positive, we can write it as well in the standard form, a·x + m·y = 1.

Iterative Method

/* This function return the gcd of a and b followed by
    the pair x and y of equation ax + by = gcd(a,b)*/
pair<int, pair<int, int> > extendedEuclid(int a, int b) {
    int x = 1, y = 0;
    int xLast = 0, yLast = 1;
    int q, r, m, n;
    while(a != 0) {
        q = b / a;
        r = b % a;
        m = xLast - q * x;
        n = yLast - q * y;
        xLast = x, yLast = y;
        x = m, y = n;
        b = a, a = r;
    }
    return make_pair(b, make_pair(xLast, yLast));
}
 
int modInverse(int a, int m) {
    return (extendedEuclid(a,m).second.first + m) % m;
}

Recursive Method

/* This function return the gcd of a and b followed by
    the pair x and y of equation ax + by = gcd(a,b)*/
pair<int, pair<int, int> > extendedEuclid(int a, int b) {
    if(a == 0) return make_pair(b, make_pair(0, 1));
    pair<int, pair<int, int> > p;
    p = extendedEuclid(b % a, a);
    return make_pair(p.first, make_pair(p.second.second - p.second.first*(b/a), p.second.first));
}
 
int modInverse(int a, int m) {
    return (extendedEuclid(a,m).second.first + m) % m;
}

3. Using Fermat’s Little Theorem
Fermat’s little theorem states that if m is a prime and a is an integer co-prime to m, then ap − 1 will be evenly divisible by m. That is a^{m-1} \equiv 1 \pmod{m}. or a^{m-2} \equiv a^{-1} \pmod{m}. Here’s a sample C++ code:

/* This function calculates (a^b)%MOD */
int pow(int a, int b, int MOD) {
int x = 1, y = a;
    while(b > 0) {
        if(b%2 == 1) {
            x=(x*y);
            if(x>MOD) x%=MOD;
        }
        y = (y*y);
        if(y>MOD) y%=MOD;
        b /= 2;
    }
    return x;
}
 
int modInverse(int a, int m) {
    return pow(a,m-2,m);
}

4. Using Euler’s Theorem
Fermat’s Little theorem can only be used if m is a prime. If m is not a prime we can use Euler’s Theorem, which is a generalization of Fermat’s Little theorem. According to Euler’s theorem, if a is coprime to m, that is, gcd(a, m) = 1, then a^{\varphi(m)} \equiv 1 \pmod{m}, where where φ(m) is Euler Totient Function. Therefore the modular multiplicative inverse can be found directly: a^{\varphi(m)-1} \equiv a^{-1} \pmod{m}. The problem here is finding φ(m). If we know φ(m), then it is very similar to above method.

vector<int> inverseArray(int n, int m) {
    vector<int> modInverse(n + 1,0);
    modInverse[1] = 1;
    for(int i = 2; i <= n; i++) {
        modInverse[i] = (-(m/i) * modInverse[m % i]) % m + m;
    }
    return modInverse;
}





转载于:https://www.cnblogs.com/tigerisland/p/7564860.html

相关文章:

  • 线程同步辅助类——CountDownLatch
  • Java中的并发工具
  • ShareSDK的使用文章
  • Linux查看程序端口占用情况
  • 如何在VS2008中自定义多项目模板
  • 程序员,我们都是夜归人【转】
  • 【架构】微服务系列文章
  • 快速查询Python脚本语法
  • 基础业务集成开发平台(BusinessWorks) - 概要设计篇
  • java基础----java调用oracle存储过程(转)
  • linux GTK 安装
  • 如果在ecshop中自定义添加模板
  • Python操作MySQL数据库
  • Java中的内部接口
  • linux gcc 编译动态类库(.so)和静态类库(.a)
  • ES6指北【2】—— 箭头函数
  • emacs初体验
  • flutter的key在widget list的作用以及必要性
  • k个最大的数及变种小结
  • MySQL几个简单SQL的优化
  • PHP的Ev教程三(Periodic watcher)
  • PHP面试之三:MySQL数据库
  • react 代码优化(一) ——事件处理
  • Vue.js-Day01
  • 从重复到重用
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 前端面试之闭包
  • 深入浅出Node.js
  • 突破自己的技术思维
  • Java总结 - String - 这篇请使劲喷我
  • kubernetes资源对象--ingress
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • #pragma pack(1)
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (4) PIVOT 和 UPIVOT 的使用
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (BFS)hdoj2377-Bus Pass
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (一)基于IDEA的JAVA基础1
  • (转)Linux下编译安装log4cxx
  • (转)visual stdio 书签功能介绍
  • (转)关于pipe()的详细解析
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET Project Open Day(2011.11.13)
  • .NET Remoting学习笔记(三)信道
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .Net程序帮助文档制作
  • .Net中的设计模式——Factory Method模式
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • []Telit UC864E 拨号上网
  • [20140403]查询是否产生日志