AcWing 876 快速幂求逆元

好久不见. 提交于 2019-12-27 03:19:00

题目描述:

给定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;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!