快速幂
什么是幂
幂是一个数自乘若干次的形式,乘方的结果叫做幂。比如
这些性质都是针对任意实数
同底数幂的乘法法则
同底数幂的除法法则
幂的幂
积的幂
商的幂
线性求幂
容易想到,求
int sum=1;
for (int i=1; i<=n; i++) sum *= a;
那能否更快呢?
快速幂
来看例题:
例题——快速幂
题目描述
给定
输入格式
第一行包含整数
接下来
输出格式
对于每组数据,输出一个结果,表示
每个结果占一行。
样例输入
2
3 2 5
4 3 9
样例输出
4
1
题目分析
首先我们需要知道幂运算的性质,
举个例子:
这样表示有什么好处呢,请看下面的式子:
易得:
这意味着什么呢?如果我们把
而把
示例代码
#include<bits/stdc++.h>
using namespace std;
long long qmi(int a, int k, int p) {
long long res = 1;
while (k) {
if (k&1) res = res*a % p; // 如果二进制上这位有数字,那么结果乘起来
k >>= 1; // 去掉最低位
a = (long long)a*a % p; // 递推求出 a^(2^x) 的值
}
return res;
}
int main() {
int a, k, p;
cin >> a >> k >> p;
cin >> a >> k >> p;
cout << qmi(a, k, p) << '\n';
return 0;
}
例题——快速幂求逆元
题目描述
给定 impossible
。
注意:请返回在
若整数
输入格式
第一行包含整数
接下来
输出格式
输出共
若 impossible
。
样例输入
3
4 3
8 5
6 3
样例输出
1
2
impossible
题目分析
在模运算中,我们都知道,加法和乘法是比较简单的:
减法因为可能由负数,所以需要加上之后再取模:
而除法取模则比较特别,这里我们需要引入逆元的概念。
逆元的概念
首先我们要来了解 单位元 和 逆元 的定义。
单位元
在一个集合中,对于某种运算,如果对于任何的集合元素
例如,在加法运算中,对于任意的实数
根据上面的概念,你可以说出乘法运算的单位元是什么么?
没错,就是
逆元
在一个集合中,对于某种运算,如果任意两个元素的运算结果等于单位元,则称这两个元素互为逆元。
例如,在普通的加法运算中,任意实数
同理,在普通的乘法运算中,任意实非零实数
模乘运算下的单位元
对于结果对
假设单位元为
根据单位元的定义,应该有:
将上面的式子带入,则有:
所以可得:
所以,模乘的单位元就是
模乘的逆元
根据逆元的定义,若
例如:
换个角度说,若
模乘逆元的一些性质:
- 模
意义,逆元一般只考虑比 小的,并且在这个范围内逆元是唯一的。 - 逆元存在的条件,
互质,那么 在模 意义下才有逆元。
这个逆元有什么用呢?在取模意义下,如果数字
那么如何求出数字的模乘逆元呢?我们先来了解一下费马小定理:
若
那么根据逆元的定义和费马小定理,我们可以进行如下推导:
假设
根据费马小定理,有:
将左边式子提取一个
所以可得,逆元
总结:
若
做法其实很简单,因为 impossible
。
示例代码
int n;
cin >> n;
while (n--) {
int a, p;
cin >> a >> p;
if (a%p == 0) cout << "impossible\n";
else cout << qmi(a, p-2, p) << '\n'; // 快速幂代码和上面一致,不再演示
}