快速幂
快速幂的用法及推导
之前算一个\(a^k\)时间复杂度是\(O(K)\).搞一个循环不断的相乘
现在是\(O(logk)\)
在30次之内算出来
核心思想:反复平方法
等号两边同时模一个数,那个大小是不变的
代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL qmi(int a, int n, int mod)
{
LL res = 1 % p; // 当 p = 1, b = 0的时候是有区别的
while(n)
{
if(n & 1) res = res * a % mod;
a = a * (LL) a % mod; // 低进制向高自动转换
n >>= 1;
}
return res;
}
int main()
{
int n;
cin >> n;
while(n--)
{
int a, b, p;
cin >> a >> b >> p;
cout << quick_mod(a, b, p) << endl;
}
return 0;
}
快速幂求逆元
背景介绍以及定义
在很多时候我们都需要进行取余运算。加减乘都很容易取余
但是除法取余数是很麻烦的一件事情,所以我们就考虑把除法的求余转换成求乘法的余数
$ a/b \equiv a * x \pmod{m}$
则称\(x\)是\(b\)的\(mod m\)的乘逆元
逆元是一个整数只是一个标记
由逆元的推导式子可得:
$ b*b^{-1} \equiv 1 \pmod{m}$
若m又由费马小定理可知:
\(b^{m-1} \equiv 1 \pmod{m}\)
化简得
\(b*b^{m-2} \equiv 1 \pmod{m}\)
所以\(b^{-1}\)就等于\(b^{m-2}\)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL qmi(int a, int b, int mod)
{
LL res = 1 % mod;
while(b)
{
if(b & 1) res = res * a % mod;
a = (LL)a * a % mod;
b >>= 1;
}
return res % mod;
}
int gcd(int a, int b)
{
return b ? gcd(b, a%b) : a;
}
int main()
{
int n;
cin >> n;
while(n--)
{
int a, p;
cin >> a >> p;
if(gcd(a, p) == 1)
{
cout << qmi(a, p - 2, p) << endl;
}
else cout << "impossible" << endl;
}
return 0;
}
题目中限定了 \(p\)一定是质数,所以如果 \(a\) 和 \(p\) 有公因子,那么 \(a\) 就一定是 \(p\) 的倍数。
有什么问题可以加qq:1281372141进行交流