快速幂和逆元

快速幂

快速幂的代码如下

#include<iostream>
using namespace std;

int qmi(int a,int k,int p) {
    int res = 1;
    while(k) {
        if(b & 1) res = (long long ) res *a %p;
        b>>=1;
        a = (long long) a* a%p;
    }
    return res;
}

int main(){
    qmi(a,b,p);
    return 0;
}

逆元

快速幂求逆元

当且仅当除数和模互质时,可以使用快速幂求逆元

a / b = a * b的逆元(mod n)

使用x表示b的逆元a / b = a * x(mod n)

两边同乘以b可得a ≡ a* b* x(mod n)

也就是 1 ≡ b* x(mod n) ……①

如果n,b互为质数,又由于费马小定理:b(n-1) ≡ 1 (mod n) ……②

[费马小定理(Fermat's little theorem)](费马小定理_百度百科 (baidu.com))是数论中的一个重要定理,在1636年提出。如果p是一个质数,而整数a不是p的倍数,则有a(p-1) ≡ 1(mod p)。

由①②可得,b* x(mod n) = b(n-1) , 即 x = b(n-2)

—————————————或者是-------------------------------------------------------------------------

左边拆出来一个b ,就可以得出b * b(n-2) ≡ 1 (mod n)

故当n为质数时,b的乘法逆元 x = b(n-2)

#include<iostream>
using namespace std;
const int mod = 1e9+7;
int ny(int x) {
    return qmi(x,mod-2, mod);
}

int main() {
    int n;
    cin>>n;
    ny(n);
}

扩展欧几里得算法求逆元

当模和除数不互质的时候,可以用扩展欧几里得算法求逆元:

a有逆元的充要条件是a与p互质,所以gcd(a, p) = 1
假设a的逆元为x,那么有a * x ≡ 1 (mod p)
等价:ax + py = 1
exgcd(a, p, x, y)

#include <iostream>
using namespace std;
typedef long long LL;
int n;

int exgcd(int a, int b, int &x, int &y)
{
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}


int main()
{
    cin >> n;
    while (n --)
    {
        int a, p, x, y;
        // if (a < p) swap(a, p);
        cin >>  a >> p;
        int d = exgcd(a, p, x, y);
        if (d == 1) cout << ((LL)x + p) % p << endl;//保证x是正数
        else puts("impossible");

    }
    return 0;
}
posted @ 2021-10-23 15:33  zzuli_DYS  阅读(92)  评论(0)    收藏  举报