非递归写法:
- 快速幂模板:
#include<stdio.h>
int Quick_pow ( int a, int b ) {
int ret = 1;
while ( b ) {
if ( b & 1 ) ///判断奇数
ret = ret * a;
a = a * a;
b >>= 1;///除以2
}
return ret;
}
int main()
{
int x,y,t;
while(~scanf("%d%d",&x,&y)){
t=Quick_pow(x,y);
printf("%d\n",t);
}
}
- 快速幂求模模板:
#include<stdio.h>
int Quick_pow_mod ( int a, int b, int mod ) {
a%=mod;/// 预处理,防止出现a比mod大的情况
int ret=1;//记录结果
while(b){
if(b&1) //如果b的二进制位不是0,那么我们的结果是要参与运算的
ret=ret*a%mod;
a=a*a%mod;//不断的加倍
b>>=1; //二进制的移位操作,相当于每次除以2,用二进制看,就是我们不断的遍历b的二进制位
}
return ret;
}
int main()
{
int n,x,m,t;
while(~scanf("%d%d%d",&n,&x,&m)){
t=Quick_pow_mod(n,x,m);
printf("%d\n",t);
}
return 0;
}
- 快速幂原理( 引用快速幂讲解)
代码很短,死记也可行,但最好还是理解一下吧,其实也很好理解,以b==11为例,b=>1011,二进制从右向左算,但乘出来的顺序是 a ^ ( 2 ^ 0) * a ^ ( 2 ^ 1 ) * a ^ ( 2 ^ 3 ),是从左向右的。我们不断的让base *= base目的即是累乘,以便随时对ans做出贡献。
由于是二进制,很自然地想到用位运算这个强大的工具:&和>> 。 &运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位。还可以判断奇偶x&1= =0为偶,x&1==1为奇。 >>运算比较单纯,二进制去掉最后一位。
其中要理解base*=base这一步:因为 base * base == base^2,下一步再乘,就是 base ^ 2 * base ^ 2 == base ^ 4,然后同理 base ^ 4 * base ^ 4 = base ^ 8,由此可以做到 base --> base ^ 2 --> base ^ 4 --> base ^ 8 --> base ^ 16 --> base ^ 32…指数正是 2^i ,再看上面的例子,a¹¹= a^1 * a^2 * a ^8,这三项就可以完美解决了,快速幂就是这样。
顺便啰嗦一句,由于指数函数是爆炸增长的函数,所以很有可能会爆掉int的范围,根据题意选择 long long还是mod某个数自己看着办。
矩阵快速幂,求斐波那契数列的矩阵快速幂模板同见快速幂讲解
递归写法:
int Q_pow(int a,int b)
{
if (b == 0) return 1;
int ret =Q_pow(a*a, b / 2);
if (b & 1) ret *= a;
return ret;
}
int Q_pow(int a,int b,int mod)
{
if (b == 0) return 1;
int ret =Q_pow(a*a, b / 2, mod);
if (b & 1) ret=ret*a%mod;
return ret%mod;
}
下面的代码和说明引用自快速幂(递归):
long long quick_pow(long long x,long long y)
{
if(y==1) return x;
if(y==0) return 1; //1,2两种情况的代码一定要放在第3种情况之前
if(y%2==0) return quick_pow(x*x,y/2);
if(y%2!=0) return x*quick_pow(x*x,y/2);
}
a^b,b总的有3种情况:
1.b=0,a^b=1;
2.b=1,a^b=a;
3.b>1:
A.b为偶数,则a^b=(a ^ 2) ^b/2=((a ^2) ^2) ^b/2/2=…,直到指数为1;
B.b为奇数,则a^b=a·a ^b-1=a·(a ^2) ^(b-1)/2重复A,B操作,直到指数为1。