2

快速(杨)幂方法总结

所谓快速幂,就是快速的进行幂运算

以下以求a的b次方来介绍[1] 
把b转换成二进制数。
该二进制数第i位的权为
例如
11的二进制是1011
11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1
因此,我们将a¹¹转化为算

比如2002122700^2002102300这种数就不是特别好算,会崩

所以我们的前辈们就发明了快速幂这种东西

而快速幂的实现有两种方式

方法1:运用递归加位运算(更简洁)

(任何数的0次方为1)

int pow(int n, int m) 
{
    if(m == 0) return 1;
    int t = pow(n, m / 2);
    t = 1LL * t * t % MD;
    if(m&1) t = 1LL * t * n % MD;    //在奇数的时候乘n
    return t;

 方法2:用for(正向的退回去)

r(1);==   r=1;这是一条赋值语句

 

int pow2(int n, int m)
{
    int r(1), s(n);
    for(; m; m>>=1, s = 1LL*s*s%MD) 
        if(m&1) r = 1LL*r*s%MD;//这样做可以保证数不出错
    return r;
}

补充一下位运算的知识

m&1;------>m%2;

m>>=1;------>m/=2;

m<<=1;------->m*=2;

当然我的理解也不是多么准确,但我找到了一篇很好的博文,供我自己大家参考

快速幂

以一道题为例,讲解快速幂算法。

 

题目:计算a^b mod c

 

朴素算法:直接计算求值。

var a,b,c,i,ans:longint;

begin

  readln(a,b,c);

  ans:=1;

  for i:=1 to b do

    ans:=ans*a;

  ans:=ans mod c;

  writeln(ans);

end.

 

以上算法有一个缺点:当a,b很大时,容易超出longint范围。

 

 

因为a^b mod c=(a mod c)^b mod c

 //(a*b)%c=(a%c)*(b%c)%c

得出改进型算法:在计算过程中不断进行mod运算

 

var a,b,c,i,ans:longint;

begin

  readln(a,b,c);

  a:=a mod c;

  ans:=1;

  for i:=1 to b do

    ans:=(ans*a) mod c;

  ans:=ans mod c;

  writeln(ans);

end.

时间复杂度:O(n)

 

这种算法也有一定缺陷:当b很大时,容易超时。

 

 

因为a^b mod c=(a^2)^(b/2) mod c   (b为偶数);

a^b mod c=((a^2)^(b div 2) *a) mod c  (b为奇数)。

 

   所以可以在计算过程中不断地将底数平方、指数除以2,用另一个变量记录最终答案。

得到快速幂算法:

 

var a,b,c,ans:int64;

begin

readln(a,b,c);

write(a,'^',b,' mod ',c,'=');

a:=a mod c;

ans:=1;

while b>0 do

    begin

    if b mod 2=1 then ans:=ans*a mod c;

    b:=b div 2;

    a:=(a*a) mod c;

end;

writeln(ans);

end.

 

时间复杂度:O(log2n),能在竞赛通过

好了,我能给大家整理的就是这些了,提前祝大家六一儿童节快乐(什么鬼),毕竟大家都还是宝宝嘛!~(~ ̄▽ ̄)~

                           

posted @ 2017-05-30 16:54  DDYYZZ  阅读(1044)  评论(0编辑  收藏  举报