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
快速幂算法求解
分析
若整数 b
,m
互质,并且对于任意的整数 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
#include
#include
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;
}