快速幂取模的用途:在ACM这类竞赛中,可能会遇到指数型的数据取模问题,这个时候如果直接用int或者long long储存,就
有可能会超出计算机整数的存取范围,而导致数据出错。所以我们需要一种方法进行计算。而这种方法就是我们这次要讲到
的快速幂取模(简称快速幂)。这种算法在时间和空间上都做了尽可能的优化,所以学会之后,会觉得非常好用。
快速幂取模的思路:快速幂实现的最基本的理论就是我们离散课上或者数论中学过的一条公式推出的引理。
引理:积的取余等于取余的积的取余。
再在这条引理的基础之上,对指数型数据进行拆分以及合并,从而得到我们用的快速幂算法。
本文我就不用例题讲解,直接对快速幂进行解析。毕竟快速幂的算法相对简单,而且适用题型较为一致。
快速幂具体分析:对a^b进行分析。
对于当a和b较小是直接用int或者long存是没有问题的,但是当a和b大到一定程度时,这就不是暴力存就
可以解决的问题了。我们应该怎么去解决这个问题呢?
在这里我们需要把注意力放在“大”字上面,正是由于a和b过大才导致的问题。所以我们要想办法不断地减
小a和b的规模,所谓逐个击破。
根据上面的那条引理,我们知道了可以把指数拆开,从这个突破口突破。这里我们就不难想到这样一个算法:
#include
using namespace std;
typedef long long LL;
const LL p=100007;
LL pow_mod(LL a, LL b, LL p){//a的b次方求余p
//引理:积的取余等于取余的积的取余。
/*LL ret =1;
while(b--)
{
ret*=a;
}
return ret;
*/
/**
a^11=a^(2^0+2^1+2^3)
11的二进制 1011
11=2^3*1+2^2*0+2^1*1+2^0*1;
a^11=a^(2^0)*a^(2^1)*a^(2^3)
**/
LL ret = 1;
while(b){
if(b & 1) ret = (ret * a) % p;///b&1 当b=1时b&1=1 其余皆为0
a = (a * a) % p;
b>>=1;
}
return ret;
}
LL mul(LL a, LL b, LL p){//快速乘,计算a*b%p
LL ret = 0;
while(b){
if(b & 1) ret = (ret + a) % p;
a = (a + a) % p;
b >>= 1;
}
return ret;
}
int main()
{
LL a,b;
cin>>a>>b;
//b>>=1;
// cout<