快速幂求解

目录

一.问题引入

二.快速幂

三.运用场景


一.问题引入

试想,如果我们想要计算一个数字的n次方,可以如何计算?

首先很容易想到以下方法:

#include<iostream>
using namespace std;

int main()
{
	long long  n,x;
	cin>>n>>x;
	
	long long res=1;
	for(int i=1;i<=x;i++)
	{
		res=res*n;
	}
	cout<<res<<endl;
	
 } 

上述方法的时间复杂度为o(x),而且当res>2^31时,最后结果不能被输出表示出来

于是有了下面的思考:

如果我们要算5^8,是不是可以这样计算:(5*5)*(5*5)*(5*5)*(5*5)

(5*5)*(5*5)*(5*5)*(5*5)

(5*5)*(5*5)*(5*5)*(5*5)

两两相乘,只需要乘以3次就可以得到结果

#include<iostream>
using namespace std;

int main()
{
   int a=5;
   a=a*a;   //5*5
   a=a*a;   //(5*5)*(5*5)
   a=a*a;   //(5*5)*(5*5)*(5*5)*(5*5) 
   
   cout<<a<<endl; 
	
 } 

这样一来,我们的时间复杂度就从o(x)降到了o(log(x))

但还是解决不了我们的问题,考虑以下方法:

二.快速幂

由进制的转换我们知道,任何正整数都能写成2^n的形式

5=2^2+2^0;

7=2^2+2^1+2^0;

10=2^3+2^1

通过以上基础知识,我们就可以将快速幂的过程转换为在求每个数的二进制时,进行2^n的相乘

举个例子: 9的二进制是 1001

5^9  =5^(2^3+2^0)

1       0      0      1 

2^3  2^2   2^1  2^0

模拟过程:

res  5^(2^0)                                    5^(2^0)*5^(2^3)

x     4                2             1                     0

n     5^(2^1)   5^(2^2)    5^(2^3)        5^(2^4)

但是问题又来了,int 最多存2^15,long long 最多存2^31, 即使是最小的2^(10^8)也不能被存储记录下来,所以,快速幂的题目一般都是会让我们求a^b后的余数,即 (a^b)%p      (p的范围为(0,2^31)) 

我们可以在算出结果a^b后再%p来求得结果,但是a^b的结果一般十分巨大,不能被存储下来,

由于模的基本运算性质:

我们分析出可以在边计算a^b的过程中%p,结果是不变的

以板子题:https://www.luogu.com.cn/problem/P1226为例,给出模版代码:

#include<iostream>
using namespace std;
long long a,x,p,n,m;
long long res=1;
//快速幂 
int main()
{
	cin>>a>>x>>p;
	//模拟二进制的算法
	n=a,m=x;  
	while(m!=0)
	{
		if(m%2==1) res=(res*n)%p;  //为奇数的话,二进制的最后一位是1,反之为0 
		m=m/2;
		n=(n*n)%p;
	}
	res=res%p;
	printf("%lld^%lld mod %lld=%lld",a,x,p,res);
	return 0;
}

时间复杂度为log(o(x))     <注意这里的x指的都是指数!>

三.运用场景

快速幂常用于某些题目的计算优化,主要还是算法思想和背板子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值