快速幂和逆元
快速幂
快速幂的代码如下
#include<iostream>
using namespace std;
int qmi(int a,int k,int p) {
int res = 1;
while(k) {
if(b & 1) res = (long long ) res *a %p;
b>>=1;
a = (long long) a* a%p;
}
return res;
}
int main(){
qmi(a,b,p);
return 0;
}
逆元
快速幂求逆元
当且仅当除数和模互质时,可以使用快速幂求逆元
a / b = a * b的逆元(mod n)
使用x表示b的逆元a / b = a * x(mod n)
两边同乘以b可得a ≡ a* b* x(mod n)
也就是 1 ≡ b* x(mod n) ……①
如果n,b互为质数,又由于费马小定理:b(n-1) ≡ 1 (mod n) ……②
[费马小定理(Fermat's little theorem)](费马小定理_百度百科 (baidu.com))是数论中的一个重要定理,在1636年提出。如果p是一个质数,而整数a不是p的倍数,则有a(p-1) ≡ 1(mod p)。
由①②可得,b* x(mod n) = b(n-1) , 即 x = b(n-2)
—————————————或者是-------------------------------------------------------------------------
左边拆出来一个b ,就可以得出b * b(n-2) ≡ 1 (mod n)
故当n为质数时,b的乘法逆元 x = b(n-2)
#include<iostream>
using namespace std;
const int mod = 1e9+7;
int ny(int x) {
return qmi(x,mod-2, mod);
}
int main() {
int n;
cin>>n;
ny(n);
}
扩展欧几里得算法求逆元
当模和除数不互质的时候,可以用扩展欧几里得算法求逆元:
a有逆元的充要条件是a与p互质,所以gcd(a, p) = 1
假设a的逆元为x,那么有a * x ≡ 1 (mod p)
等价:ax + py = 1
exgcd(a, p, x, y)
#include <iostream>
using namespace std;
typedef long long LL;
int n;
int exgcd(int a, int b, int &x, int &y)
{
if (!b) {
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main()
{
cin >> n;
while (n --)
{
int a, p, x, y;
// if (a < p) swap(a, p);
cin >> a >> p;
int d = exgcd(a, p, x, y);
if (d == 1) cout << ((LL)x + p) % p << endl;//保证x是正数
else puts("impossible");
}
return 0;
}

浙公网安备 33010602011771号