题目描述:
给定n组ai,pi,其中pi是质数,求ai模pi的乘法逆元,若逆元不存在则输出impossible。
注意:请返回在0∼p−1之间的逆元。
乘法逆元的定义
输入格式
第一行包含整数n。接下来n行,每行包含一个数组ai,pi,数据保证pi是质数。
输出格式
输出共n行,每组数据输出一个结果,每个结果占一行。若ai模pi的乘法逆元存在,则输出一个整数,表示逆元,否则输出impossible。
数据范围
1≤n≤10^5,1≤ai,pi≤2∗10^9
输入样例:
3
4 3
8 5
6 3
输出样例:
1
2
impossible
分析:
首先引入欧拉定理:
欧拉定理就是说对于两个互质的数a和n,a^phi(n)与1对模n同余。下面简单的证明下欧拉定理:设1到n中与n互质的数的集合为S = {p1,p2,...,pk}。设集合R = {a*p1%n,a*p2%n,...,a*pk%n},假设R中存在两项a * pi ≡ a * pj (mod n),则a * (pi - pj)≡ 0 (mod n),又a与n互质,所以pi ≡ pj (mod n),又pi和pj都是S中两个与n互质的整数,故不可能模n同余,故R中不存在两项相同的数,也就是说R中的数彼此互异且都与n互质,又因为mod n后都小于n,而1到n中与n互质的数全在S中,故S = R。故R中各项相乘得a^phi(n) * p1p2...pk ≡ p1p2...pk (mod n)故a^phi(n) ≡ 1 (mod n)。欧拉定理得证。
当n为质数时,phi(n) = n - 1,代入欧拉定理得到a^(n - 1) ≡ 1 (mod n),这就是费马小定理。
继续讲乘法逆元的定义,a / b ≡ a * x (mod m),在mod m前提下,对a除以b相当于对a乘上了x,则x就是b的模m乘法逆元。对等式两边都乘上b得到a ≡ a * x * b (mod m),即x * b ≡ 1 (mod m)。又由费马小定理知b与m互质且m是质数时,a^(m - 1) ≡ 1 (mod m),故x = b^(m-2)。所以求乘法逆元只需要用快速幂求下b的m-2字方即可。
最后,如果b是m的倍数,则x * b ≡ 1 (mod m)不可能成立,此时乘法逆元不存在。
#include <iostream>
using namespace std;
typedef long long ll;
ll binaryPow(ll a,ll b,ll p){
ll ans = 1 % p;
while(b){
if(b & 1) ans = ans * a % p;
a = a * a % p;
b >>= 1;
}
return ans;
}
int main(){
int n;
cin>>n;
while(n--){
int a,p;
cin>>a>>p;
if(a % p) cout<<binaryPow(a,p - 2,p)<<endl;
else cout<<"impossible"<<endl;
}
return 0;
}
来源:CSDN
作者:昂昂累世士
链接:https://blog.csdn.net/qq_30277239/article/details/103706087