『数论』乘法逆元

在求解除法取模问题\((a \div b) \mod m\)时,我们可以转化为\([a \mod (b \times m)]\div b\)

但是如果\(b\)很大,则会出现爆精度问题,所以我们避免使用除法直接计算。

可以使用逆元将除法转换为乘法:假设\(b\)存在乘法逆元,即与\(m\)互质(充要条件)。

设\(c\)是\(b\)的逆元,即\(b \times c≡1(\mod m)\)

那么有\(a\div b=(a\div b)\times 1=(a\div b)\times b\times c=a\times c(\mod m)\)

除以一个数取模等于乘以这个数的逆元取模

  • 逆元求解一般利用扩欧。
  • 当\(m\)为质数的时候直接使用费马小定理,\(m\)非质数使用欧拉函数。
  • 当\(m\)为质数的时候,神奇的线性方法。

扩展欧几里得算法

要求\(a,m\)互素,存在唯一解。

int extgcd(int a, int b, int &x, int &y) {
    int d=a;
    if (b!=0) {
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else {
        x=1;
        y=0;
    }
    return d;
}
int mod_inverse(int a, int m) {
    int x, y;
    extgcd(a, m, x, y);
    return (m+x%m)%m;
}

费马小定理

在\(p\)是素数的情况下,对任意整数\(x\)都有\(x^{p}≡x(\mod p)\)。

如果\(x\)无法被\(p\)整除,则有\(x^{p}-1≡1(\mod p)\)。

可以在\(p\)为素数的情况下求出一个数的逆元,\(x \times x^{p}-2≡1(\mod p)\),\(x^{p}-2\)即为\(x\)的逆元。

LL mul(LL a, LL n) {//求a ^ n % mod
    LL s=1;
    while (n) {
        if (n&1) s=s*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return s;
}
//mul(a, n-2);

欧拉函数

令\(\phi(m)\)表示小于等于\(m\)且与\(m\)互素的正整数的个数。

如果\(x\)和\(m\)互质,则有\(x\phi (m)≡1(\mod m)\),即\(x\times x\phi (m)-1≡1(\mod m)\),\(x^{\phi(m)-1}\)为\(x\)的逆元。

在\(m\)为质数的情况下,\(\phi (m)=m-1\),即为费马小定理。

思路:

求出欧拉函数的值,利用欧拉函数的积性性质

对于任意整数\(n\),可以将它分解\(n=p_{k1} \times p_{k2} \times p_{k3} \times \cdots \times p_{km}\),其中\(p_{i}\)为质数,\(\phi(n)=\phi(p_{k1}) \times \phi(p_{k2})\times \cdots \phi(p_{km})\)

最后转化为\(\phi(n)=n \times \prod(p_{i}-1) \div p_{i}\)

对给定\(n\)进行整数分解,时间复杂度\(O(n)?\)。

int eurler_phi(int n) {
    int res=n;
    for (int i=2; i*i<=n; i++) {
        if (n%i==0) {
            res=res/i*(i-1);
            while (n%i==0) n/=i;
        }
    }
    if (n!=1) res=res/n*(n-1);
    return res;
}

埃氏筛法求欧拉函数值的表,每次发现质因子就把他的倍数的欧拉函数乘上\((p-1)\times p\)。

当\(n\)为奇数时,有\(\phi(2\times n)=\phi(n)\)

因为\(2\times n\)是偶数,偶数与偶数一定不互素,所以只考虑\(2n\) 与小于它的奇数互素的情况,则恰好就等于\(n\)的欧拉函数值。

int euler[maxn];
void euler_phi2() {
    for (int i=0; i<maxn; i++)
        euler[i]=i;
    for (int i=2; i<maxn; i++)
        if (euler[i]==i)
            for (int j=i; j<maxn; j+=i)
                euler[j]=euler[j]/i*(i-1);
}

线性时间求所有逆元

规定\(p\)为质数,且\(1^{-1}≡1(\mod p)\)

设\(p=k\times a+b(b<a,1<a<p)\),即\(k\times a+b≡0(\mod p)\)

两边同时乘以\(a^{-1}\times b^{-1}\),得到

\(k\times b^{-1}+a^{-1}≡0(\mod p)\)

\(a^{-1}≡-k\times b-1(\mod p)\)

\(a^{-1}≡-p\div a×(p\mod a)^{-1}(\mod p)\)

从头开始扫一遍即可,时间复杂度\(O(n)\)。

int inv[maxn];
inv[1]=1;
for (int i=2; i<maxn; i++)
    inv[i]=(p-p/i)%p*inv[p%i];

原文地址:https://www.cnblogs.com/shenxiaohuang/p/10162141.html

时间: 2024-10-15 08:40:14

『数论』乘法逆元的相关文章

数论 - 最小乘法逆元

我只能说这个数论定理对我一脸懵比,哦不对,是我对这个数论定理一脸懵比,暂时 只准备记住模板就好了,求最小逆元的时候可以用一下,如果mod为素数而且不要求 最小的话还是用费马小定理吧,对了还是要说一下,这个模板中exgcd(扩展欧几里德) 的返回值是gcd(最大公约数),其中x才是要求的逆元,而且一求出来时并不是最小 而且还有可能是负数,有点分类讨论了,不过我找模板的时候把分类讨论那里用一个更 优的方案代替了(也是找的),用的时候注意点,不说了,我还是准备懵比去吧= = #include<iost

『数论』求最大公因数

//#define fre yes #include <cstdio> int gcd(int a, int b) { if(b != 0) gcd(b, a % b); else return a; } 谈论数论不废话 ----- 辗转相除法求gcd 以上代码的时间复杂度为 \(O(\log n)\) 证明,为何 \(gcd(b, a \mod b) = gcd(a, b)\) 设 \(g = gcd(a, b)\) 那么一定有 \(a = xg , b = yg\) 我们又可以将 a 用

数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho

数论入门2 另一种类型的数论... GCD,LCM 定义\(gcd(a,b)\)为a和b的最大公约数,\(lcm(a,b)\)为a和b的最小公倍数,则有: 将a和b分解质因数为\(a=p1^{a1}p2^{a2}p3^{a3}...pn^{an},b=p1^{b1}p2^{b2}p3^{b3}...pn^{bn}\),那么\(gcd(a,b)=\prod_{i=1}^{n}pi^{min(ai,bi)},lcm(a,b)=\prod_{i=1}^{n}pi^{max(ai,bi)}\)(0和任何

数论学习之乘法逆元

用法:用于除法取模 思路:扩欧 要求:b.p互质 设k为b的乘法逆元: 则在求解除法取模问题时: 有(a/b)%p =>(a*k)%p 当b很大时,用除法会出现精度问题..so 乘法逆元: 如果b*k ≡ 1 (mod p) 则称k是b关于p的乘法逆元 我们可以通过求 b 关于 p 的乘法逆元 k,将 a 乘上 k 再模 p,即 (a * k) mod p.其结果与(a / b) mod p等价. 证: 因为 b * k ≡ 1 (mod p) 则有 b * k = p* x+1 得到 k =

数论--乘法逆元

乘法逆元 定义: 满足a*k≡1 (mod p)的k值就是a关于p的乘法逆元. 为什么要有乘法逆元呢?当我们要求(a/b) mod p的值,且a很大,无法直接求得a/b的值时,我们就要用到乘法逆元. 我们可以通过求b关于p的乘法逆元k,将a乘上k再模p,即(a*k) mod p.其结果与(a/b) mod p等价. 证:(其实很简单...) 根据b*k≡1 (mod p)有b*k=p*x+1. k=(p*x+1)/b. 把k代入(a*k) mod p,得: (a*(p*x+1)/b) mod p

SWJTU2017-6月月赛 G-A Easy Counting Problem[数论][乘法逆元]

传送门:http://www.swjtuoj.cn/problem/2397/ 题解:产生交点的条件为4个点构成四边形对角线产生交点,最大解当产生的交点位置完全不相同时存在.答案为$C_{\text{n}}^4$ 计算组合数时需要使用乘法逆元 代码: 1 #define _CRT_SECURE_NO_DEPRECATE 2 #pragma comment(linker, "/STACK:102400000,102400000") 3 #include<iostream> 4

「数论基础」 乘法逆元

定义:若$ab ≡ 1\ (mod\ p)$,则称$b$是$mod\ p$意义下$a$的乘法逆元 可以将逆元记作$inv$,则$a * inv ≡ 1\ (mod\ p)$ 其实定义反过来也是成立的,即$a$是$mod\ p$意义下$b$的乘法逆元 乘法逆元的意义: 模运算中的除法是不符合四则运算法则的,然而加减乘都符合.所以数学家们利用乘法逆元来完成除法的需求. 完成除法的工作——经典应用:求解$a / b \% p\  (b | a)$ 方法: 设$a / b \% p = r$ 则$a /

2016&quot;百度之星&quot; - 资格赛(Astar Round1)-(模拟+线段树+乘法逆元)

Problem A Accepts: 1351 Submissions: 9951 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description 度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长很长的字符串.现在麻烦来了,他忘记了原来的字符串都是什么,神奇的是他竟然记得原来那些字符串的哈希值.一个字符串的哈希值,由以下公式计算得到: H

CodeForces 300C Beautiful Numbers(乘法逆元/费马小定理+组合数公式+快速幂)

C. Beautiful Numbers time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Vitaly is a very weird man. He's got two favorite digits a and b. Vitaly calls a positive integer good, if the decimal