zoukankan      html  css  js  c++  java
  • 逆元

    在比赛中我们会遇到形如 (A/B)%MOD 的式子(比如说组合数学中求组合数),但是由于取模对除法没有分配律,所以我们只能乖乖的先算 A/B 再对结果进行取模吗?当A、B较小的时候还行,当A、B很大的时候就不适用了,因为A/B会丢失精度。我们可以将上述式子改写一下 (A/B)%MOD 改为 (A * inv(B)) %MOD 这样一来除法就变为乘法了,这样一来精度就有保证了,上式再进一步改写为 (A%MOD * inv(B) %MOD) % MOD 这里的 inv(B) 就表示B关于MOD的逆元,当GCD(MOD, B) == 1时B才有唯一的逆元。

    逆元:对于正整数a和m,如果有a * x = 1 (mod m)  则称 x 为 a 关于 m 的逆元,比如 2 * 3 % 5 = 1, 这样一来就相当于 3 是 2 关于 5 的逆元;

    下面介绍几种求逆元的方法

    1、费马小定理:

    当MOD为素数的时候,会有 inv(B) =  pow(B, MOD-2) 这样的公式,这个最好求,我们利用快速幂计算,O(logn)时间复杂度之内就可以求出来结果。

    2、扩展欧几里得:(练习扩欧可以试试这个很经典的题目:https://vjudge.net/problem/POJ-1061 )

    我们先介绍扩展欧几里得算法,扩欧算法可以求出 ax + by = gcd(a, b) 的一对整数解 (x, y) ,下面是扩展欧几里得算法:

    1 //d就是gcd(a,b), (x,y)就是式子 ax+by=gcd(a,b) 的一个解
    2 void exgcd(int a, int b, int& d, int& x, int& y){
    3     if(!b) { d = a; x = 1; y = 0; }
    4     else { exgcd(b, a%b, d, y, x); y -= x*(a/b); }
    5 }

    这样一来就好办了,这个方程的解 x 就是 a 关于 b 的逆元,就是 b 关于 a 的逆元,但是得注意扩欧求出来的x,y可能是负数或者是0,这个时候我们需要将 得到的逆元进行处理,一般是( inv%MOD + MOD ) % MOD 

    3、欧拉函数:这个先不写了

    练习逆元可以试试这题: https://vjudge.net/problem/HDU-1576

  • 相关阅读:
    iphone、UI设计和PKM的混谈
    社保名单核对的难题
    LVDS技术原理和设计简介
    系统级芯片设计语言和验证语言的发展
    芯片封装(Chip Package)类型70种
    数字电平标准 TTL CMOS ECL LVDS CML...
    什么是施密特触发器(Schmitt Trigger)?
    组合逻辑电路中竞争冒险的分析
    ASIC设计流程(ASIC design flow)
    这18条背下来没人敢和你忽悠CPU
  • 原文地址:https://www.cnblogs.com/DynastySun/p/9362505.html
Copyright © 2011-2022 走看看