zoukankan      html  css  js  c++  java
  • 啥是快速幂

    啥是快速幂

    这篇文章是为了帮一个同学学习ksm写的

    百度百科给的定义:

    顾名思义,快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。

    这是一种能够快速的计算出(a^b)的值的算法

    如果暴力计算(a^b)需要把a乘自己b次,当b太大时,就会超时。

    使用ksm就只用log₂b次,计算次数大大减小。

    原理:

    1. 将a乘自己a*a=(a^2),再做同样的操作(a^2 *a^2=a^4);所以a自乘n次后就是(a^2n).

    2. (a^x *a^y=a^(x+y))

    3. 对于b,只要它是一个正整数,都可以把它拆成若干个2的不同次幂相加。

      如:11=(2^3+2^1+2^0)

      而11的二进制就是1011,也就是计算机里所储存的形式,更方便去对于b进行上述拆分。

    过程:

    定义两个数,temp和ans;temp即为要进行自乘的数初始值为上文所说的a;ans初值为1,即为答案,(为什么是1呢,自己思考)。

    while(b)//也就是当b大于0时
    

    先判断b的最后一位是否为1

    如果是就将ans*=temp;

    if(b&1) ans=(1longlong*ans*temp);
    

    关于 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。
    挺巧妙的,并且很快。

    之后将temp自乘,变成(a^2);

    同时将b右移一位。

    即:若b=11(10),二进制下b=1011(2);

    右移一位就变成b=101(2);

    temp=(1longlong*temp*temp);
    b=>>1;
    

    不断重复上述过程直到不满足while的条件b>0;

    代码实现:

    以luoguP1226为例

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long 
    using namespace std;
    
    ll b,p,k;
    
    ll ksm(ll a,ll b,ll z)//快速幂函数
    {
    	//这里的temp可以直接用a来表示,不影响结果,可以自己想为什么
        ll ans=1;
    	while(b)
    	{
    		if(b&1) ans=(1ll*ans*a)%z;
    		a=(1ll*a*a)%z//自乘
    		b>>=1;//右移
    	}
    	return ans;
    }
    
    int main()
    {
    	scanf("%lld%lld%lld",&b,&p,&k);
    	printf("%lld^%lld mod %lld=%lld",b,p,k,ksm(b,p,k)%k);
    	return 0;
    }
    
  • 相关阅读:
    团购网站之大众点评
    cas xml
    smsUtil
    solr配置
    xml
    yu
    Schema.xml
    ApplicationContext-redis.xml
    fast
    第一版
  • 原文地址:https://www.cnblogs.com/plzplz/p/12081233.html
Copyright © 2011-2022 走看看