快速幂详解

来源:互联网 发布:cms系统源码 编辑:程序博客网 时间:2024/06/03 22:08
1.首先说快速幂是用处:
快速幂顾名思义,就是快速算某个数的多少次幂。
其时间复杂度为 O(lgN)快速幂详解--by <wbr> <wbr>viking 比朴素的O(N)快了不知多少啊!!!

以下以求a的b次方来介绍

2.快速幂的原理:
把b转换成2进制数
该2进制数第i位的权为a^(2^(i-1))
例如
a^11=a^(2^0+2^1+2^3)
11的二进制是1011
     即: 11 = 2^3*1  +  2^2*0  +  2^1*1  +  2^0*1               
so:我们将a^11转化为算a^(2^0)*a^(2^1)*a^(2^3)

3.那么要怎么实现呢??位运算是强大的工具!!
b and 1 //也就是取b的二进制最末位
b shr 1 //就是去掉b的二进制最末位
有了这个强大的工具,快速幂就好实现了!

var a,b,n:int64;
function f(a,b,n:int64):int64;
var t,y:int64;
begin
  t:=1;y:=a;
  while b<>0 do
  begin
    if (b and 1)=1 then t:=t*y mod n;
    y:=y*y mod n; //这里用了一个很强大的技巧,y*y即求出了 a^(2^(i-1)) ←不知道这是什么的看原理
    b:=b shr 1;
  end;
  exit(t);
end;
begin
read(a,b,n); // n是模
write(f(a,b,n));
end.


下面是代码实现比较:

常规求幂

int pow1( int a, int b ){    int r = 1;    while( b-- )        r *= a;    return r;}

二分求幂(一般)

int pow2( int a, int b ){    int r = 1, base = a;    while( b != 0 )    {        if( b % 2 )            r *= base;        base *= base;        b /= 2;    }    return r;}

快速求幂(位操作)

int pow3( int a, int b ){    int r = 1, base = a;    while( b != 0 )    {        if( b & 1 )            r *= base;        base *= base;        b >>= 1;    }    return r;}

快速求幂(更高效率的位运算法)

int pow4(int x, int n){    int result;    if (n == 0)        return 1;    else    {        while ((n & 1) == 0)        {            n >>= 1;            x *= x;        }    }    result = x;    n >>= 1;    while (n != 0)    {            x *= x;        if ((n & 1) != 0)            result *= x;        n >>= 1;    }    return result;}

0 0