逆元Inv(模板+应用)

Posted sykline

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆元Inv(模板+应用)相关的知识,希望对你有一定的参考价值。

逆元:

如果满足公式技术分享图片,则有a 是 b的逆元同时b也是a的逆元。

逆元的应用:

设c为b在对m取余的意义下的逆元;

在求解公式 (a / b) % m的时候,如果b可能会非常的大,所以会出现爆精度的问题,这个时候就需要将除法转换成乘法来做,即:

(a / b )  % m = (a * c)%m。

逆元的求法:

一、扩展欧几里得求逆元

复杂度:O(logn)(实际就是斐波那契数列)

将公式(b、p已知)   a?b≡1(mod p)   转换为   a?b+k?p=1  则有a为b对p取余意义下的逆元,且只有当a与p互质是逆元才存在

注意:只要存在逆元就可以求,适用于逆元个数不多,但是mod很大的时候。

附一个百度百科的例子加深一下理解:

技术分享图片技术分享图片?

代码:

/*
    Time:2018/8/31
    Writer:Sykai
    Function:利用扩展欧几里得求逆元
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e6 + 100;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> P;

//公式a?b+k?p=1中a即是a,p即是b
ll exgcd(ll a,ll b,ll& x,ll& y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    ll res = exgcd(b, a%b, y, x);
    y -= a/b*x;
    return res;
}
//公式a?b+k?p=1中a即是a,p即是mod
ll getInv(int a,int mod)//求a在mod下的逆元。如果不存在就返回-1
{
    ll x,y;
    ll res = exgcd(a,mod,x,y);
    return res = 1 ? (x%mod + mod)%mod:-1;//return res = 1?(x + mod)%mod : -1;
}

int main()
{
    ll a = 5;
    printf("%lld
",getInv(a,MOD));
    return 0;
}

二、费马小定理求逆元

复杂度:O(logn)

费马小定理: 假如p是质数,且gcd(a,p)=1,那么 a^(p-1)≡1(mod p)。

a*a^(p-2) ≡ 1 (mod p),则有a^(p-2)是a的对p取余时候的逆元

注意:当p是素数的时候一般选用费马小定理来求逆元。

代码:

/*
    Time:2018/8/31
    Writer:Sykai
    Function:利用费马小定理求逆元
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e6 + 100;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> P;

ll qpow(ll a,ll b)//求a*a^(p-2) ≡ 1 (mod p)中a^(p-2)
{
    ll res = 1;
    while(b)
    {
        if(b&1)
            res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}

ll getInv(ll a,ll mod)
{
    return qpow(a,mod-2);
}

int main()
{
    int a = 5;
    printf("%lld
",getInv(a,MOD));
    return 0;
}

三、递推求逆元

复杂度:O(n)

注意:

1、mod需要是质数,求得是1~N关于mod的逆元。

2、适用于mod不是太大,且被多次调用。

3、程序开始前需要预处理打表。

代码:

/*
    Time:2018/8/31
    Writer:Sykai
    Function:线性求逆元
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e6 + 100;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> P;
ll inv[maxn];//数组的大小需要根据实际情况来调整

void getInv()
{
    inv[1] = 1;
    for(int i = 2; i < maxn; i++)
        inv[i] = (MOD-MOD/i)*inv[MOD%i]%MOD;
}

int main()
{
    getInv();
    printf("%lld
",inv[5]);
    return 0;
}

四、递归求逆元

复杂度:O(logn)

注意:mod需要是素数(中国剩余定理中不太好用)

/*
    Time:2018/8/31
    Writer:Sykai
    Function:递归求逆元
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e6 + 100;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> P;
ll inv[maxn];//数组的大小需要根据实际情况来调整

ll getInv(ll x)
{
    if(x == 1) return 1;
    return (MOD-MOD/x)*getInv(MOD%x)%MOD;
}

int main()
{
    printf("%lld
",getInv(5));
    return 0;
}

五、求阶乘的逆元

代码:(不确定怎么用)

/*
    Time:2018/8/31
    Writer:Sykai
    Function:递归求逆元
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e6 + 100;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> P;
ll inv[maxn];//数组的大小需要根据实际情况来调整
ll fac[maxn+1];//阶乘数组
ll qpow(ll a,ll b)
{
    ll res = 1;
    while(b)
    {
        if(b&1)
            res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}


int main()
{
    inv[maxn] = qpow(fac[maxn],MOD-2);
    for(ll i = maxn-1; i>=0; i--)
    {
        inv[i] = (inv[i+1]*(i+1))%MOD;
    }
    return 0;
}

参考博客:

https://blog.csdn.net/baidu_35643793/article/details/75268911

https://blog.csdn.net/xiaoming_p/article/details/79644386

 

以上是关于逆元Inv(模板+应用)的主要内容,如果未能解决你的问题,请参考以下文章

逆元求组合数

题解 P3811 模板乘法逆元

P3811 模板乘法逆元

模板:逆元求解

[洛谷P3811]模板乘法逆元

组合数+逆元