快速幂精解

来源:互联网 发布:学法语的软件 编辑:程序博客网 时间:2024/05/16 09:55

快速幂的原理及使用

1.预备知识:c语言的位运算法则(正好也方便自己以后查阅)

c语言提供了6种位运算符:& 按位与、| 按位或、^ 按位异或、~ 取反、<< 左移、>> 右移

1.1按位与运算

按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进制相与,只有对应的两个二进制位均为1时,结果位才为1,否则为0.参与运算的数以补码方式出现。

例如:9&5
00001001(9的二进制补码)&00000101(5的二进制补码)=00000001(1的二进制补码)
所以9&5=1。

按位与运算通常用来对某些位清0或保留某些位。例如把a的高8位清0,保留低8位,可作a&255运算(255的二进制数为0000000011111111)。

1.2按位或运算

按位或运算符"|"是双目运算符。其功能是参与运算的两位数各对应的二进制位相或。只要对应的两个二进制位有一个为1时,结果位就为1.参与运算的两个数均以补码出现。

例如:9|5
00001001(9的二进制补码)|00000101(5的二进制补码)=00001101(13的二进制补码)

1.3按位异或运算

按位异或运算符"^"是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进制相异时,结果位为1。参与运算的数任以补码出现。
例如:9^5
00001001(9的二进制补码)^00000101(5的二进制补码)=00001100(十进制为12)

1.4求反运算

求反运算符~为单目运算符,具有右结合性。其功能是对参与运算的数的各二进制位按位求反。
例如:~9
~(00001001)=11110110

1.5左移运算

左移运算符"<<"是双目运算符。其功能把"<<"左边的运算数的各二进制位全部左移若干位,由"<<"右边的数指定移动的位数。高位丢弃,低位补0。
例如:a<<4
指把a的各二进制位向左移动4位,a=00000011(十进制3),左移4位后为00110000(十进制48)。

1.6右移运算

右移运算符">>"是双目运算符。其功能把">>"左边的运算数的各二进制位全部右移若干位,由">>"右边的数指定移动的位数。
例如:a>>2
指把a的各二进制位向右移动2位,a=00001111(十进制15),右移2位后为00000011(十进制3)

对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1,最高位补0还是补1取决于编译系统的规定。但大多数都规定补1。

2.幂运算的原理

首先,快速幂的目的就是做到快速求幂,假设我们要求a^n,按照朴素算法就是把a连乘n次,这样求解时间复杂度自然是O(n),而快速幂能做到O(logn)。当我们求a^n时,其实n可以拆成二进制,该二进制数第i位的权为2^(i-1),例如当n==11时:
a^11=a^(2^0+2^1+2^3)
11的二进制是1011,11=2^3*1+2^2*0+2^1*1+2^0*1,因此我们将a^11转化为a^(2^0+2^1+2^3)。

3.幂运算的应用

由于是二进制,很自然地想到用位运算这个工具:&和>> 
       &运算通常用于二进制取位操作,例如一个数&1的结果就是取这个二进制数的末位。而且还可以用来判断奇偶:x&1==0为偶数,x&1==1为奇数。
      >>运算将二进制向右移若干位,高位补0。

求解a^11的算法如下:
typedef long long LLLL poww(LL a,LL n){LL ans=1,base=a;while(n!=0){if(n&1)ans*=base;base*=base;n>>=1;}return ans;}

代码解释:

1.首先定义一个long long 的数据类型(防止越界);
2.然后是赋初值;
3.一个while循环,假如n为0了,退出循环,返回ans,否则继续循环;
4.if判断,取n二进制的末位,如果不为0,就令ans*=base,否则什么也不做;
5.base*=base的目的是利用上一次计算出来的结果;
6.最后一步是n>>=1,它的意思是将n的二进制数右移一位,并且将结果重新赋给变量n。


1 0
原创粉丝点击