C语言实现快速幂的递归与迭代求解

1. 问题描述:

给定三个正整数a,b(a < 10 ^ 9,b < 10 ^ 18,1 < m < 10 ^ 9)求解出a ^ b % m

2. 思路分析:

① 对于上面这个问题,最简单的思路是使用一个循环来进行累乘,直到累乘的次数等于了b那么循环就结束了,但是假如按照这样的思路来解决,对于O(b)的时间复杂度为O(10 ^ 8)都比较难支持了,更何况是10 ^ 18呢?所以上面的解法是不行的

② 这里需要使用到快速幂的计算,首先我们可以使用递归的方法来进行求解,下面是求解的式子:

1)如果b是奇数,那么有 a ^ b = a * a ^ (b - 1);

2)如若b是偶数,那么有a ^ b = a ^ (b / 2) * a ^ (b / 2);

从上面的式子我们可以知道对于b是奇数的情况下是能够转化为偶数的,而b是偶数的情况下我们是可以先转换为b / 2的情况,在经过若干次的转换之后那么最后到达了递归的边界就是b变成了0的情况,这个时候我们直接返回1就可以了,a ^ 0 = 1

③ 比如要求解出 2 ^ 10,我们需要经过下面的步骤:

1)由10是偶数因此先要求解 2 ^ 5,然后2 ^ 10 = 2 ^ 5 * 2 ^ 5;

2)对于2 ^ 5来说,5是奇数,所以先要求解出2 ^ 4,2 ^ 5 = 2 * (2 ^ 4)

3)对于2 ^ 4来说,4是偶数,所以先要求解出2 ^ 2,2 ^ 4 = 2 ^ 2 * 2 ^ 2

4)对于2 ^ 2来说,2是偶数,所以先要求解出2 ^ 1,2 ^ 2 = 2 ^ 1 * 2 ^ 1

5)对于2 ^ 0来说,1是奇数,所以先要求解出2 ^ 0,2 ^ 1 = 2 * 2 ^ 0

6)2 ^ 0 = 1递归结束

3. 下面是具体的代码:

#include<stdio.h>
typedef long long LL;
LL binaryPow(LL a, LL b, LL m){
	if(b == 0) return 1;
	//b为奇数那么那么转换为b-1
	if(b % 2 == 1) return a * binaryPow(a, b - 1, m);
	//b为偶数 
	else{
		LL mul = binaryPow(a, b / 2, m);
		return mul * mul % m;
	}
} 

int main(void){
	//使用%lld来进行存储与输出 
	LL a, b, m;
	scanf("%lld%lld%lld", &a, &b, &m);
	printf("%lld", binaryPow(a, b, m)); 
	return 0;
}

4.  除了上面的递归求解的方法之外,我们还可以使用递推的方法来进行求解,思路分析如下:

① 首先比如我们需要求解出2 ^ 10,10的二进制形式为1010,所以2 ^ 10 = 2 ^ 8 * 2 * 2得到,而8,2对应的是10这个幂的二进制位上是否是1,,这样我们使用递推的思路就比较清晰了,下面是具体的步骤:

1)初始的时候可以令ans = 1

2)判断b的二进制位数是否是1,使用b & 1 == 1来进行判断,b & 1进行位与操作这样比 b % 2 == 1来判断的执行速度会更快

3)令a平方,并且b后移1位相当于是b /= 2

4)只要是b大于0那么就回到2)

5. 下面是具体的代码:

#include<stdio.h>
typedef long long LL;
LL binaryPow(LL a, LL b, LL m){
	LL ans = 1; 
	while(b > 0){
		//下面的if判断相当于判断b的最后一位是1还是0 
		if(b & 1 == 1){
			ans = ans * a % m;
		}
		a = a * a % m;
		//b除以2 
		b >>= 1;	
	}
	return ans; 
} 

int main(void){
	LL a, b, m;
	scanf("%lld%lld%lld", &a, &b, &m);
	printf("%lld", binaryPow(a, b, m)); 
	return 0;
}
发布了498 篇原创文章 · 获赞 133 · 访问量 50万+

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/94758703