快速幂(自己的一些理解)

一、涉及到的位运算

   例子:int a=10;

             a>>=1;//10的二进制为1010,>>运算符的意义简单来讲就是将二进制最右边几位去掉,这里a>>=1后,a的二进制为101

                         //此时a=5,和a/=2的效果一样,但>>更快。该运算在快速幂中很关键

                         //a>>=2,就是将a的二进制最右边2位去掉,和a/=4效果一样

二、深入(以小推大)

   一、例子:3的9次方(3为底数,9为幂)

              1、9的二进制为1001,整数的二进制从右到左的每一位的位权分别为:1,2,4,8,16....(9=2^0+2^3=1+8)

              2、根据9的二进制,我们可以将3^9写为3^1*3^8

              3、我们再看一下9的二进制,(设最右边为第一位)第一位和第四位的基数为1且权值分别为1和8。由此可以知道,当幂的二进 制的某一位为1时,我们的结果中就有乘以以该位的位权为幂,以原底数为底数的数,这里底数为3

                

               总结:1.写代码时,我们要想办法判断幂的二进制哪几位为1,此时就要用到标题一里的位运算

                         2.然后就是我们计算的时候二进制每一位对应的要乘进结果的数为多少,此时可以令要乘的数,每次循环都自乘一次

                            举例说明更方便



    二、举例解释总结:还是3的9次方(a=3,b=9,num=1)(num用于保存结果)

                                    b的二进制是1001



                                  1. 进行第一次判断:b的二进制末位为1,该位要进行运算num*=a,此时a是3^1,num=a^1;然后b>>=1,

                                      因为当前末位已经判断过了,需要判断下一位,将末位去掉,现在b的二进制为100;最后,a*=a,自乘,

                                      现在a=3^2(这样是为了下一次判断,即二进制第2位,位权为2)



                                  2.  进行第二次判断:b的二进制末位为0,该位不进行运算;然后b>>=1,b二进制变为10;a*=a,现在a=3^4

                                        (下一次判断是二进制的第3位,位权为4)

                                        

                                  3.  进行第三次判断:b的二进制末位为0,该位不进行运算;然后b>>=1,b二进制变为1;a*=a,现在a=3^8

                                        (下一次判断是二进制的第4位,位权为8)



                                  4.  进行第四次判断:b的二进制末位为1,该位进行运算num*=a,此时a=3^8,则num=3^1*3^8;然后b>>=1

                                        b现在等于0;a*=a,现在a=3^16(下一次如果进行判断就是第5位,位权16,a的值始终和位权同步)



                                   5. b=0结束判断,现在num=3^1*3^8=3^9,为我们要的值

三、代码

 #include<stdio.h>//这里使用C语言来写代码
 #define ll long long//假设我们可能会求很大的值
 #define MOD 200000//如果结果超过200000,对200000求模
  
 int main()
 {
     ll a,b;//a的b次方
     scanf("%lld %lld",&a,&b);
     ll num=1;    //用于保存结果
     while(b)    //当b不为0时进行判断
     {
        if(b&1)    //判断b的二进制的最右位是否为1,为1则进入
        {
           num=num*a%MOD;    //num乘上当前二进制位对应的数a(a为原底数为底,幂为当前二进制位的位权的数),这里取模无影响
        }
        b>>=1;    //每次判断后,将b的二进制最后一位消掉,以进行下一次判断
        a=a*a%MOD;    //每次判断后,a都要自乘,以达到一直和下一次判断的二进制的位权相对应的效果,这里取模无影响
     }
     printf("%lld\n",num);    //最后输出num即可
     return 0;    //该方法比暴力算法快许多
 }
  
  
 //感觉写的有点复杂,第一次写,排版不好看。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值