• 快速幂


    原理分析

           求a^n的值,按照传统的写法就是用一个数ans = 1 ,乘n次a,这样的时间复杂度为O(n),而快速幂算法是基于二进制,可以将时间复杂度将为log(n)

           举个例子,我们要求3^11,我们可以写成  3^(2^3+2^1+2^0),拆开后就是3^(2^3) = 3 ^ 8 、3^(2^1)=3^2 、 3^(2^0) = 3^1 , 这样看来,如果我们只计算这三个的乘积,岂不是只需要计算3次?而且这三个数之间是很有规律的,

           比如  (3^1)^2 = 3^2 , ( (3^2)^2) ^2 = 3 ^8,就是对一个数不断的取二次幂,由于任意整数都可以用二进制的数来表示,也就是说我们可以将任意整数拆解成3^(2^3+2^1+2^0)这样的形式(为了方便,我们将要求的数记作a^n) , 而对于2^k是否出现,取决于n在二进制表示下第k+1位数是否为1 。 为了更加清晰的解释,我们分析一下 11 这个数,其二进制的表示形式为 1011 , 对应出现了第4 , 2 , 1 位数,于是与之对应的2^3  , 2^1 , 2^0 也就出现了。

           上面我们解释了任意整数都可以写成  a ^ (2 ^ m + 2 ^ k .... )的形式,而且对于 m+ 1= k 的情况时,存在

      (a^(2^m)) ^ 2 = a^(2^m+1) = a^(2^k) , 再根据2^k的出现规律,我们只需要将2^k从 k = 0 开始,不断地取二次幂,如果n在二进制下的第k+1位数为1,我们用ans记录当前的值,这时候将a(2^k)乘入ans 中,最后我们就得到了最终的答案

    代码区

    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    
    ll pow_fast(ll a, ll n)
    {
    	ll ans = 1;
    	while (n != 0)
    	{
    		if (n & 1 != 0)ans =ans*a;
    		a = a * a;
    		n >>= 1;
    	}
    	return ans;
    }
    
    int main()
    {
    	cout << pow_fast(2, 5) << endl;
    	return 0;
    }
  • 相关阅读:
    错误: 找不到或无法加载主类/java BB.class 中文乱码
    如何新建git仓库并连接以及git branch相关命令
    String、StringBuffer与StringBuilder区别
    HTML选择器
    java中的system.out.println()和JSP中out.println()区别
    校园双选会,你都懂么
    android visible invisible和gone的区别
    Android 显示意图和隐式意图的区别
    android doGet和doPost
    Android 监听SMS短信
  • 原文地址:https://www.cnblogs.com/winter-bamboo/p/10634444.html
Copyright © 2020-2023  润新知