洛谷上的题目:P1226 【模板】快速幂||取余运算
1.如何让计算机很快地求出a^b?
方法1:暴力循环
if(b==0)
a==1;
while(int i=0;i<b-1;i++)
{
a*=a;
}
(当然,如果是这样,肯定不能称得上是“快速”幂。暴力相乘的话,电脑要计算 b 次)
方法2:巧用二进制快速幂
如果用快速幂,计算次数在log2(b) 级别,实用很多。
(1)把 a 自乘一次,就变成了 a^2 。然后把 a^2 再自乘一次就会变成 a^4 。然后是 a^8…… 乘n次后的结果是 a^{2^{n}}。
(2)a^xa^y = a^{x+y}
(3)b 的二进制:比如 b = (11)_{10}即 (1011)_{2} 。这就是十进制的 8,2,1。可那么 a^{11} = a^8 × a^2 × a^1
为啥要这样表示?因为我们要他通过自乘得到b次。而这个b我们恰好可以通过他的二进制分成几个数的和。比如11,分成8,2,1,这样恰好可以通过a的自乘得到。
过程
·拿到了 a,并且 b = 11。想求 a^{11}
·以电脑视角稍稍观察一下 b = 11,二进制下是 b = 1011b=1011。
·定义base。现在 base = a,表示a^1 = a。
·定义 ans,初值是 1
当然,如果最后要用二进制来做,可以用操作符巧妙判断b二进制最后一位
if(b & 1)
ans *= base;
/* 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。
巧妙,而且很快。)*/
然后 basebase ,自乘一次,变成 a^2。
base *= base;
同时
b >>= 1;
所以就是这样
int quickPower(int a, int b)
{
int ans = 1;
int base = a;
while(b > 0)
{
if(b & 1)
ans *= base;
base *= base;
b >>= 1;
}
return ans;
}
取余
(m+n)moda=(mmoda+nmoda)moda
(m×n) \mod a = ((m \mod a) × (n \mod a)) \mod a(m×n)moda=((mmoda)×(nmoda))moda
然后把这个放到快速幂里面,减小运算时的数据
while(b > 0)
{
if(b & 1)
{
ans *= base;
ans %= m;
}
base *= base;
base %= m;
b >>= 1;
}