zoukankan      html  css  js  c++  java
  • 乘法逆元

    1.使用情况:

      用法1.在求解除法取模问题(a/b)%m时,我们可以转化为(a%(bm))/b, 
      但是如果b很大,则会出现爆精度问题,所以我们避免使用除法直接计算。 

      用法2.当我们要求(a/b) mod m的值,且a很大,无法直接求得a/b的值时,我们就要用到乘法逆元。
      我们可以通过求b关于p的乘法逆元k,将a乘上k再模p,即(a*k) mod m。其结果与(a/b) mod m等价。

     

      遇到上面的情况,我们可以使用逆元将除法转换为乘法: 

      假设b存在乘法逆元,即与m互质(充要条件)。设c是b的逆元,即bc1(modm)

      那么有a/b=(a/b)1=(a/b)bc=ac(modm) 

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

    2.方法:

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

    3.代码:

    #include<cstdio>
    #include <math.h>
    using namespace std;
    typedef long long ll;
    const int p = 1e9 + 7;
    const int N = 1e5 + 5;
    ll inv[N];
    
    ll inv1(ll a)//递推法求逆元
    {
        return a==1?1:(p-p/a)*inv1(p%a)%p;
    }
    
    void inv2(ll n)//通过递推进行逆元打表
    {
        inv[1] = 1;
        for (ll i=2; i<=n; ++i)
        {
            inv[i] = (ll) (p - p / i) * inv[p%i] % p;
        }
    }
    
    void exgcd(ll a,ll b,ll& d,ll& x,ll& y)
    {
        if(!b)
        {
            d = a;
            x = 1;
            y = 0;
        }
        else
        {
            exgcd(b, a%b, d, y, x);
            y -= x*(a/b);
        }
    }
    ll inv3(ll a)//扩展欧几里得
    {
        ll d, x, y;
        exgcd(a, p, d, x, y);
        return d == 1 ? (x+p)%p : -1;
    }
    
    ll inv4(ll a, ll b)//费马小定理
    {
        ll res = 1;
        while(b)
        {
            if(b&1)
                res = (res*a)%p;
            b = b>>1;
            a = (a*a)%p;
        }
        return res;
    }
    
    int main()
    {
        ll b;
        while(1)
        {
            scanf("%lld",&b);
            ll ans1=inv1(b);
            printf("%lld
    ",ans1);
            inv2(100);//100以内的数对P的逆元
            ans1=inv[b];
            printf("%lld
    ",ans1);
            ans1=inv3(b);
            printf("%lld
    ",ans1);
            ans1=inv4(b,p-2);
            printf("%lld
    ",ans1);
        }
    }

      

  • 相关阅读:
    Linux下如何查看版本信息
    java单利模式设计
    MIT 2012 分布式课程基础源码解析-底层通讯实现
    MIT 2012分布式课程基础源码解析-事件管理封装
    MIT 2012分布式课程基础源码解析-线程池实现
    MIT 2012分布式课程基础源码解析一-源码概述
    Leetcode按Tag刷题
    网页搜集系统
    c/c++中的各种字符串转换
    gentoo装X服务器时显卡选择
  • 原文地址:https://www.cnblogs.com/aiguona/p/7642683.html
Copyright © 2011-2022 走看看