逆元概念与模板

来源:互联网 发布:linux入门教程下载 编辑:程序博客网 时间:2024/06/16 00:56

如果两个数a和b,它们的乘积关于模m余1,我们称它们互为关于模m的数论倒数,⼀般形式为:a *b≡1(mod m)

还有⼀种形式是:对于正整数a和m,如果有a⋅x≡1(mod m),那么把这个同余⽅程中x的最⼩正整数解叫做a模m的逆元。

⽽我们要处理的⼀个⼤问题,就是如何去求逆元。

有的题⽬要求结果mod⼀个⼤质数,如果原本的结果中有除法,⽐如除以a,那就可以乘以a的逆元替代



下⾯介绍两种求逆元的⽅法:

【1】欧拉函数(费马⼩定理求逆元)

  φ:N→N,n→φ(n)称为欧拉函数。对正整数n,欧拉函数的值是少于或等于n的数中与n互质的数的数⽬。

  此外有欧拉定理:设a,m∈N,(a,m)=1(即a与m互质,最⼤公约数为1),则a^φ(m) ≡1(mod m),根据上边的性质我
  们可以了解到,当m为质数时,欧拉函数的值为m-1。由此可得欧拉定理的⼀个特殊情况:
                                                                a^(m-1) ≡ 1(mod m)
                                                              (m为质数且a与m互质)
  这就是⼤名⿍⿍的费马⼩定理。它是欧拉定理的⼀个特殊情况,我们观察这个式⼦,是不是有些似曾相识?
  没错,将式⼦稍微变形,我们就可以得到
                                                                a*a^(m-2) ≡≡ 1(mod m)

  也就是说,a关于m的逆元正是a^(m-2) 。于是,当a与m互质时,我们仅需使⽤快速幂求出a^(m-2) 的值即可。时间复
  杂度O(√n)。要求:a和M互质,且M为质数。


  代码: 

///M 必须是质数const long long M = 1000000007;long long quickpow(long long a, long long b){    if (b < 0)    {        return 0;    }    long long ret = 1;    a %= M;    for (; b; b >>= 1, a = (a * a) % M)        if (b & 1)        {            ret = (ret * a) % M;        }    return ret;}long long inv(long long a){    return quickpow(a, M - 2);}


【2】拓展欧⼏⾥得求逆元

  拓展欧⼏⾥得算法可以求出ax+by=gcd(a,b)=d的整数解。那利⽤拓展欧⼏⾥得算法如何求乘法逆元呢?很简
  单,我们对逆元的⽅程做⼀个简单的变换。
                                                        a⋅x≡1(mod m)  <=> a*x+m*y=1
  这⾥我们可以看到,当gcd(a,m)不为1的时候,⽅程是⽆解的。也就是说我们只需求出⼀个x的解,即可得出a
  的逆元。但题⽬往往要求我们求最⼩的逆元,⾮常简单,直接让x%m即可。时间复杂度O(loga),要求互素
 (m不⼀定要是素数)

  代码:

///需要与M 互质const long long M = 1000000007;long long exgcd(long long a, long long b, long long &x, long long &y){    if (b == 0)    {        x = 1;        y = 0;        return a;    }    long long ans = exgcd(b, a % b, x, y);    long long temp = x;    x = y;    y = temp - (a / b) * y;    return ans;}long long inv(long long a){    long long x, y;    long long t = exgcd(a, M, x, y);    if (t != 1)    {        return -1;    }    return (x % M + M) % M;}

求ax ≡c(mod b)

typedef long long LL;LL e_gcd(LL a, LL b, LL &x, LL &y){    if (b == 0)    {        x = 1;        y = 0;        return a;    }    LL ans = e_gcd(b, a % b, x, y);    LL temp = x;    x = y;    y = temp - a / b * y;    return ans;}LL cal(LL a, LL b, LL c)  ///求ax = c(mod b){    LL x, y;    LL gcd = e_gcd(a, b, x, y);    if (c % gcd != 0)    {        return -1;    }    x *= c / gcd;    b /= gcd;    if (b < 0)    {        b = -b;    }    LL ans = x % b;    if (ans <= 0)    {        ans += b;    }    return ans;}


  线性处理1~n的逆元
  刚刚的两种⽅法全部要求a和m需要互质,但是有的题⽬两个数并不互质,这时我们有⼀种不需要a和m互质的算法

 (但依然要求m为质数),线性处理法。
  先说结论,这个算法可以去求1,2,3,…,N关于m的逆元(m为质数),x^(-1) ≡−(y/x)*(y mod x)^(-1) (mod y)

  这样通过迭代我们可以得到从1~n的所有逆元,复杂度o(n).

  证明过程略;代码如下:

const int mod = 1000000009;const int maxn = 10005;int inv[maxn];inv[1] = 1;for (int i = 2; i < 10000; i++){    inv[i] = inv[mod % i] * (mod - mod / i) % mod;}




原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 蹲起膝盖有响声怎么办 腰突然不能弯了怎么办 蚂蚱吃了会过敏怎么办 孕妇能吃蚂蚱菜怎么办 孕妇吃了蚂蚁菜怎么办 白果很硬的时候怎么办 有痔疮吃了胡椒怎么办 吃紫菜多了难受怎么办 四川泡菜太酸了怎么办 孕妇吃了白花菜怎么办 怀孕吃了马扎菜怎么办 被铁钉扎伤了脚怎么办 风扇吹得肩膀疼怎么办 胳膊肌肉那块肿了怎么办 生完孩子臀部变宽怎么办 3岁宝宝肋骨外翻怎么办 胸肌正面不明显侧面看才有怎么办 小孩胸肌骨突出外翻怎么办 衣柜隔层板坏了怎么办 科三路线记不住怎么办 喂奶以后胸变小了怎么办 健身完肩膀缝疼怎么办 生过孩子胯部宽怎么办 无肩带文胸往下滑怎么办 内衣肩带老是往下滑怎么办 乳房发育一边大一边小怎么办 母猫乳房有硬块怎么办 19岁乳晕很大乳头很小怎么办 做完俯卧撑胳膊特别痛怎么办 电压低风扇转不动怎么办 小孩不配合康复锻炼怎么办 跑步机安全开关脱落怎么办 办健身卡贵了怎么办 跑步机安全锁丢了怎么办 老公的腿老是疼怎么办 跑步机钥匙丢了怎么办 跑步机磁铁丢了怎么办 瑜伽拉筋拉伤了怎么办康复 大腿拉筋拉伤了怎么办 肚子饿的咕咕叫怎么办 手表折叠扣松了怎么办?