输入样例:
2
3 2 5
4 3 9
输出样例:
4
1
注意:
b&1就是判断b的二进制表示中第0位上的数是否为1,若为1,b&1=true,反之b&1=false 还不理解?进传送门
b&1也可以用来判断奇数和偶数,b&1=true时为奇数,反之b&1=false时为偶数
#include<iostream>
using namespace std;
long long qmi(long long a,int b,int p)
{
long long res=1;
while(b)//对b进行二进制化,从低位到高位
{
//如果b的二进制表示的第0位为1,则乘上当前的a
if(b&1) res = res *a %p;
//b右移一位
b>>=1;
//更新a,a依次为a^{2^0},a^{2^1},a^{2^2},....,a^{2^logb}
a=a*a%p;
}
return res;
}
int main()
{
int n;
cin>>n;
while(n--)
{
int a,b,p;
long long res=1;
cin>>a>>b>>p;
res = qmi(a,b,p);
cout<<res<<endl;
}
return 0;
}
二、快速幂求逆元(费马定理)
输入样例:
3
4 3
8 5
6 3
输出样例:
1
2
impossible
费马小定理:
假如p是质数,且gcd(a,p)=1,那么 a^(p-1)≡1(mod p)。即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。
当n为质数时,可以用快速幂求逆元:
a / b ≡ a * x (mod n)
两边同乘b可得 a ≡ a * b * x (mod n)
即 1 ≡ b * x (mod n)
同 b * x ≡ 1 (mod n)
由费马小定理可知,当n为质数时
b ^ (n - 1) ≡ 1 (mod n)
拆一个b出来可得 b * b ^ (n - 2) ≡ 1 (mod n)
故当n为质数时,b的乘法逆元 x = b ^ (n - 2)
当n不是质数时,可以用扩展欧几里得算法求逆元:
a有逆元的充要条件是a与p互质,所以gcd(a, p) = 1
假设a的逆元为x,那么有a * x ≡ 1 (mod p)
等价:ax + py = 1
exgcd(a, p, x, y)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int qmi(int a,int b,int q)
{
int res=1;
while(b)
{
if(b&1)res=(ll)res*a%q;
b>>=1;
a=(ll)a*a%q;
}
return res;
}
int main()
{
int n;
cin>>n;
while(n--)
{
int a,b,p;
cin>>a>>p;
int res=qmi(a,p-2,p);
if(a%p) cout<<res<<endl;
else cout<<"impossible"<<endl;
}
return 0;
}