zoukankan      html  css  js  c++  java
  • 让计算机很快地求出a^b%c;

    让计算机很快地求出ab
    暴力相乘的话,电脑要计算 b 次。用快速幂,计算次数在 log 2(b) 级别,很实用。
    原理 I
    (1)如果将 a 自乘一次,就会变成 a2 。再把 a2 自乘一次就会变成 a4 。然后是 a^8
    …… 自乘 n 次的结果是 a^2 n

    (2)axay = ax+y,这个容易。

    (3)将 b转化为二进制观看一下:

    比如b=(11)10 就是 (1011) 2 。从左到右,这些 11 分别代表十进制的 8,2,18,2,1。可以说 a11= a8 × a2 × a1
    为什么要这样表示?因为在快速幂的过程中,我们会把 a 自乘为 a^2
    ,然后 a2a 自乘为 a4……像上面第一条说的。
    过程会是这样:
    (好长,可以不看,如果要阅读下面的模拟过程的话,要慢慢地看噢)·假设我们拿到了 a,并且 b=11。想求 a^11 ,但是又不想乘11次,有点慢。·以电脑视角稍稍观察一下 b=11,二进制下是 b=1011。·制作一个 base。现在 base=a,表示的是,a1 = a。待会base会变的。·制作一个 ansans,初值 11,准备用来做答案。

    while(b > 0)
    {
    

    ·循环一。看b(二进制)的最后一位是 1 吗? 是的。这代表 a11= a8×a2×a1 中的“ ×a1 ”存在。所以 ans *= base。

    if(b & 1)
        ans *= base;
    
    /*关于 b & 1:
    “&”美名曰“按位与”。
    x & y 是二进制 x 和 y 的每一位分别进行“与运算”的结果。
    与运算,即两者都为 1 时才会返回 1,否则返回 0。
    那么 b & 1
    
      二进制
    
    b     =    1011
    1     =    0001
    b&1   =    0001
    
    因为 1(二进制)的前面几位全部都是 0,
    所以只有 b 二进制最后一位是 1 时,b & 1 才会返回 1。
    挺巧妙的,并且很快)*/
    

    ·然后 basebase 努力上升,他通过自乘一次,使自己变成 a2

    base *= base;
    

    同时

    b >>= 1;
    

    它把(二进制的)自己每一位都往右移动了。原来的最后第二位,变成了最后第一位!b=(101) 2

    }
    

    ·循环二,再看看 b,最后一位还是 1。这说明有“ ×a 2 ”,ans∗=base。 继续努力,通过 base∗=base 让自己变成了 a 4 。然后 b 也右移 一位,b=10。循环三,可是 b 的最后一位不再是 1 了,说明不存在“ × a4 ”。base 自我升华,达到了 a8 。且 b>>=1。这一步中,答案没有增加,可是毕竟 b>0,还有希望。·循环四,b 的最后一位是 1,这说明“ ×a8 ”的存在。ans *= base。由于 b 再右移一位就是 0 了,循环结束。

    总的来说,如果 b在二进制上的某一位是 1,我们就把答案乘上对应的 。不懂的话,请结合代码理解~
    实现

    int quickPower(int a, int b)//是求a的b次方
    {
        int ans = 1, base = a;//ans为答案,base为a^(2^n)
        while(b > 0)//b是一个变化的二进制数,如果还没有用完
        {
            if(b & 1)//&是位运算,b&1表示b在二进制下最后一位是不是1,如果是:
                ans *= base;//把ans乘上对应的a^(2^n)
    
            base *= base;//base自乘,由a^(2^n)变成a^(2^(n+1))
            b >>= 1;//位运算,b右移一位,如101变成10(把最右边的1移掉了),10010变成1001。现在b在二进制下最后一位是刚刚的倒数第二位。结合上面b & 1食用更佳
        }
        return ans;
    }
    

    取余运算
    快速幂经常要结合取余运算。这里也讲一点。

    取余运算有一些好用的性质,包括:

    (A+B) mod b = (A mod b + B mod b) mod b
    (A×B) mod b = ((A mod b) × (B mod b)) mod b
    证明都很简单,如果要说服自己的话拿起笔试试吧。可设 A = k_A × b + R_A
    于是快速幂过程中可以

    while(b > 0)
    {
        if(b & 1)
        {
            ans *= base;
            ans %= m;
        }
    
        base *= base;
        base %= m;
        b >>= 1;
    }
    

    能保证这样下来最后的结果与“先乘到最后,再取余”的结果一样。

  • 相关阅读:
    泛社交泛泛之交也很重要
    iOS 切后台挂机
    iOS 导航栏translucent用法
    iOS 中UIButton中文字换行
    iOS 给UIimageView添加UITapGestureRecognizer手势点击事件
    iOS15UITableView多了白条,导航栏和Tabbar变成白色和标题变黑处理总结属性变化和原来基本的导航栏属性总结记录(看到就更新)
    iOS延时定时功能
    iOS uiview添加背景图案
    iOS 导航栏返回把样式带回前面怎么办
    iOS 识别图片二维码demo,复制粘贴即用
  • 原文地址:https://www.cnblogs.com/yonglin1998/p/11780817.html
Copyright © 2011-2022 走看看