写题解旨在记录自己算法的学习过程
题目理解:
求a的b次方对p取模的结果
输入格式
三个整数 a,b,p,在同一行用空格隔开。
输出格式
输出一个整数,表示
a^b mod p
的值。数据范围
0≤a,b ≤10^9
1≤p≤10^9
考点:
1.取模运算的性质:
[注]:模运算对于学算法的同学来说是需要记住的,虽然我这题的时候没记住hhhh
加法:(a + b) % p = (a % p + b % p ) % p (1)
减法:(a - b) % p = (a % p - b % p ) % p (2)
乘法:(a * b) % p = [(a % p) * (b % p)] % p (3)
高阶次取模:(a ^ b)% p= ((a % p) ^ b) % p (4)
2.快速幂运算
错解:不能使用pow函数,因为pow的返回值为double类型,而且转成int后会出现精度损失,得不到正确的结果;
同理使用一层for循环会超时,因为时间复杂度为O(N)
long long int ex(int a, int b)
{
long long int result = 1;
for (int i = 1; i <= b; i++)
result *= a;
return result;
}
提示:以下是本篇文章正文内容,下面案例可供参考
一、快速幂计算方法
正确方法:使用位运算的方法
例如a =2 ,b=11;
2的11次方可以拆分为以下四项之积:
、
、
、
的系数分别为1、0、1、1
11的二进制数为1011,恰好和以上四个数对应
2^3、2^2、2^1、2^0,可以看成是计算1011各个位数的十进制数
那么我们就可以推出计算快速幂的方式:
①将指数转换为二进制数,例如将11转换为二进制数 1011
②判断每一位二进制数是否为1 ,为1的话就将其乘上a对应的次方
long long int quick_ex(int a, int n)
{
long long int result = 1; //用于存储项累乘与返回最终结果,由于要存储累乘所以要初始化为1
while (n> 0) //退出条件为n为0
{
if (n& 1){ //n的最后一位为1就累乘
result *= a; //累乘当前项并存储
}
//例如1001的当前计算位就是1, 100*1* 星号中的1就是当前计算使用的位
a*= a; //计算下一个项,例如当前是n^2的话计算下一项n^2的值
n>>= 1; //指数位右移,确保每次n&1时都是和n的二进制数的最后一位进行比较
//一次的右移将舍弃一个位例如1011(2)一次左移后变成101(2)
}
return result; //返回最终结果
}
本题的计算代码如下:
#include <iostream>
using namespace std;
long long ex(long long a, long long n, long long mod) {
long long res = 1;
while (n) {
if (n & 1) {
res = res * a % mod;
}
a = a * a % mod;
n = n >> 1;
}
return res % mod;
}
int main() {
long long a, n, mod;
cin >> a >> n >> mod;
cout << ex(a, n, mod);
return 0;
}