快速幂

参考: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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值