快速幂及快速幂求模(模板)【时间复杂度O(logN)】

非递归写法:

- 快速幂模板:

#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。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 快速是一种用于快速计算运算的算法,其基本思想是将指数进行二进制拆分,然后利用指数的二进制表示来快速计算运算。在计算过程中,可以利用取余运算来避免数值溢出,提高计算效率。快速算法的时间复杂度为O(logn)。 具体实现时,可以使用递归或循环的方式来实现快速算法。在递归实现中,需要注意处理指数为负数的情况。在循环实现中,需要注意处理指数为0的情况。 取余运算可以使用%运算符来实现,其含义是两个数相除的余数。在快速算法中,取余运算可以避免数值溢出,提高计算效率。需要注意的是,在取余运算中,除数不能为0。 综上所述,快速算法和取余运算是计算运算时常用的算法和运算符,能够提高计算效率,避免数值溢出。 ### 回答2: 快速算法是一种优化指数运算的算法,通常用于对大整数进行多次乘方运算。该算法的基本思想是将指数拆分成二进制的形式,然后利用指数的二进制表示逐步计算。 具体来说,假设要计算a^b mod c的值,其中a、b、c均为正整数,那么可以先将b转换为二进制的形式,然后从右往左遍历这个二进制数,每次将当前位的值乘到结果中,同时对结果取,然后将底数a自乘一次,且也要对结果取。最终得到的结果就是a^b mod c的值。 例如,假设要计算3^13 mod 7的值,将13转换为二进制的形式得到1101,从右往左遍历这个二进制数,开始时结果为1,底数为3,当前位是1,那么将3乘到结果中,并对结果取得到3,底数自乘得到9 mod 7 = 2;下一位是0,直接将底数自乘,即2*2 mod 7 = 4;再下一位是1,将底数自乘得到16 mod 7 = 2,同时将2乘入结果,结果为3×2 mod 7 = 6;最后一位是1,将底数自乘得到4 mod 7 = 4,同时将4乘入结果,结果为6×4 mod 7 = 3,因此3^13 mod 7的值为3。 快速算法的优点是可以快速地计算指数运算,具有较好的时间复杂度。同时,取运算的存在可以避免产生过多的中间结果,节省了空间复杂度。然而,快速算法的缺点是需要将指数转换为二进制形式,这可能会增加算法的编程难度。 ### 回答3: 快速是一种用于运算的快速算法。在进行取余运算时,快速算法能够通过对结果取,使得计算结果更为精确。在计算大数据的的运算时,常常可以使用快速的算法来进行加速运算。 快速的算法可以使用递归的方式实现,也可以使用循环的方式实现。递归实现的代码比较简单,但是存在栈空间过大的问题;循环实现的代码虽然有一定的难度,但是能够避免栈空间过大的问题。 在进行取余运算时,我们需要注意的是,如果运算的两个数都很大,那么我们在计算结果时需要特别小心。因为如果直接进行计算,可能会导致数据类型溢出,进而产生错误的结果。为了避免这种情况,我们可以在进行计算时,对结果进行取处理。 在进行取运算时,我们需要使用取定理,也就是(a*b)%p=(a%p)*(b%p)%p。通过这种方式,可以使得计算结果更为精确,也可以避免数据类型溢出的情况发生。如果无法使用取定理,则需要使用高精度的算法进行取余运算。 总而言之,快速算法是一种非常有效的运算算法,可以快速地计算出大数据的运算结果。在进行取余运算时,需要特别注意数据类型溢出的问题,在进行计算时需要特别小心。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值