acwing 876. 快速幂求逆元

题目描述

给定 nn 组 ai,pi其中 pi是质数,求 ai 模 pi 的乘法逆元,若逆元不存在则输出 impossible

注意:请返回在 0∼p−1 之间的逆元。

乘法逆元的定义

若整数 b,mb,m 互质,并且对于任意的整数 aa,如果满足 b|ab|a,则存在一个整数 xx,使得 a/b≡a×x(modm)a/b≡a×x(modm),则称 xx 为 bb 的模 mm 乘法逆元,记为 b−1(modm)b−1(modm)。
bb 存在乘法逆元的充要条件是 bb 与模数 mm 互质。当模数 mm 为质数时,bm−2bm−2 即为 bb 的乘法逆元。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个数组 ai,pi数据保证 pipi 是质数。

输出格式

输出共 n 行,每组数据输出一个结果,每个结果占一行。

若 ai 模 pi的乘法逆元存在,则输出一个整数,表示逆元,否则输出 impossible

数据范围

1≤n≤105
1≤ai,pi≤2∗109

输入样例:

3
4 3
8 5
6 3

输出样例:

1
2
impossible

快速幂算法求解

分析

若整数 bm 互质,并且对于任意的整数 a,如果满足 b|a,则存在一个整数 x,使得 a / b ≡ a * x (% m),则称 x b 的模 m 乘法逆元,记为 \(b^{−1}(\% m)\)

根据费马小定理\(b^{m-1} ≡ 1 (\% m)\)

所以有\(b*b^{m-2} ≡ 1 (\% m)\)

又因为b存在乘法逆元的充要条件为b,m互质,所以当m为质数的时候,b的逆元就是\(b^{m-2}\%m\)

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

typedef long long ll;

ll ksm(int a, int b, int p)
{
    ll res = 1;
    ll t = (ll)a;
    while(b)
    {
        if(b&1) res = (res * t) % p;
        
        t = (t * t) % p;
        b >>= 1;
    }
    return res;
}

int main()
{
    int n;
    int a, p;
    
    scanf("%d", &n);
    while(n--)
    {
        scanf("%d%d", &a, &p);
        if(a % p == 0) puts("impossible"); // 数据保证了p是质数,判断a和p是否互质,只需要看p是不是a的因子
        else    printf("%d\n", ksm(a, p-2, p));
    }
    return 0;
    
}

时间复杂度

参考文章

posted @ 2022-02-25 16:09  VanHope  阅读(33)  评论(0编辑  收藏  举报