快速幂运算 c++

如果要求 a^b %m 简单的用循环就能出来,但是复杂度 O(b)在,a,b很大的时候复杂度就很高了,在算法笔记上介绍了两种算法
1.递归思想
快速幂基于二分的思想,有时也称二分幂
(1) 如果b是奇数,那么 a^b=a * a^b-1
(2)如果b是偶数,那么a^b=a ^b/2 * a ^b/2
这样在log(b) 级别的次数转换后,就可以把 b 变成0 ,而任何正整数的0次方都是1 ,这也是递归的边界
比如x ^ 10
x ^ 5 -> x * x ^ 4 求 x ^ 4
x ^ 4 -> x ^ 2 **x ^ 2 求 x ^ 2
x ^ 2 -> x^1 * x ^ 1 求 x ^ 1
x ^ 1 -> x * x ^ 0 结束

typedef long long LL;
LL binaryPow(LL a, LL b, LL m){
	if(b == 0) return 1;
	if(b & 1) return a * binaryPow(a,b-1,m) % m;
	else {
		LL ans = binaryPow(a,b/2,m) %m;
		return ans * ans %m;
	} 	
} 

& 是与运算 ,这样执行更快,也可以写成 b % 2 == 1
递归的时候不要写成 binaryPow(a,b/2,m) %m * binaryPow(a,b/2,m) %m,这样复杂度会变高
2.迭代写法
比如 2 ^ 13 可以写成 13 = 2^3 + 2^2 + 2 ^0
而13 的二级制是 1101 正好对应 幂次 ,也就是说如果当前的二进制上为1就表明22i有数,就要乘上对应的数字,其实很好理解

typedef long long LL;
LL binaryPow(LL a, LL b, LL m){
	LL ans =1;
	while(b > 0){
		if(b & 1) ans = ans * a % m;
		a * = a;
		b >> 1; //将b的二进制右移1未,相当于 b/=2; 
	}
	return ans;
}

快速幂的递归写法和迭代写法 效率都差不多 看你个人喜欢哪一种
有一道水题用递归写的,虽然很简单,但是第一次写的时候没大有思路,正好其中有一步和递归的写法相似

//水序列
//描述
//
//有个水序列如下:1 1 2 2 5 9 12 …其通项公式为f(n) = f(n-1)+f(n-2)-f(n-3) ( 4 <= n <= 30)此时,如果f(n)为奇数,还要再乘以2再减去1。给出一个整数n,请你求出该序列第n个位置上的元素。
//
//
//输入
//
//多组输入,每行一个整数n。
//
//
//输出
//
//对每组输入,单独输出一行,为第n个位置上的元素。
//
//
//输入样例 1 
//
//2
//3
//4
//5
//输出样例 1
//
//1
//2
//2
//5
#include<iostream>
#include<cstdio>
using namespace std;
int f(int n){
	if(n == 1 || n == 2) return 1;
	if(n == 3) return 2;
	if(n >= 4){
		int ans = f(n-1) + f(n-2) - f(n-3);
		if(ans & 1) return ans * 2 - 1;
		return ans;
	} 
}
int main(){
	int n;
	while(scanf("%d",&n) != 0){
		cout<<f(n)<<endl;
	}
	
	
	return 0;
} 
 

递归的写法比一开始接触写的熟练多了,但是还是要勤于练习

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值