参考:https://www.cnblogs.com/sun-of-Ice/p/9330352.html
1、快速幂
首先,快速幂的目的就是做到快速求幂,假设我们要求a^b,
假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当b==11时
a^11=a(2^0+2^1+2^3)
11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 a2^0*a2^1*a2^3,也就是a1*a2*a8
,看出来快的多了吧.原来算11次,现在算三次可以考虑成根据二进制的权值来求解的。那么在关于位运算的部分,我们可以逐位获取b的位,碰到0,就累乘,碰到1,就将累乘的值并且将乘到答案
//a^e 如果e是11 11-》1011 因此a^11=a^2_0*a^2_1*a^2_3
int pow_mod(int a,int e,int mod){
int ans=1;
int base=a%mod;
while(e){//第一次进入while的时候base是a^2_0,之后就是a^2_1,之后就是a^2_2,a^2_2,=a^2_1*a^2_1
if((e&1)==1)
ans=(ans*base)%mod;
base=(base*base)%mod;
e=e>>1;
}
return ans%mod;
}
2、斐波那契快速幂
//快速幂只是通过二进制拆分𝑛来加速幂运算的手段,当然并不只适用于求取数字的幂次,对于矩阵的𝑛次方,也可以用同样的手段求取。 //利用矩阵的幂次,我们可以快速地完成递推。
也可以看作{0,1}*{(0,1),(1,1)}^(n-1)
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int MOD=10000;
void mul(int f[2] ,int a[2][2]){
int c[2];
memset(c,0,sizeof(c));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
c[i]=(c[i]+(long long)f[j]*a[j][i])%MOD;
memcpy(f,c,sizeof(c));
}
void mulself(int a[2][2]){
int c[2][2];
memset(c,0,sizeof(c));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
c[i][j]=(c[i][j]+(long long)a[i][k]*a[k][j])%MOD;
memcpy(a,c,sizeof(c));
}
int pow_fibonacci(){
int n;
while(~scanf("%d",&n)){
if(n==-1) break;
int f[2]={0,1};
int a[2][2]={{0,1},{1,1}};
//相当于f*a^n。也就是f就是前面的ans。
while(n){
if(n&1) mul(f,a);//f是当前乘积的结果,
mulself(a);
n>>=1;
}
printf("%d\n",f[0]);
}
return 0;
}