快速乘法(俄罗斯农民乘法)和快速幂
快速乘法
在一般的竖式乘法 a × b a \times b a×b中,我们通常把 b b b的每一个位和 a a a乘,我们能不能把 b b b换成二进制,并用二进制的每一位和 a a a相乘呢?
这就要用到快速乘法了,拿 88 × 99 88 \times 99 88×99为例:
88 × 99 = 88 × 110001 1 ( 2 ) 88 × 1 × 2 0 + 88 × 1 × 2 1 + 88 × 0 × 2 2 + 88 × 0 × 2 3 + 88 × 0 × 2 4 + 88 × 1 × 2 5 + 88 × 1 × 2 6 88 \times 99 = 88 \times 110 0011_{(2)} \\ 88 \times 1 \times 2^{0} + \\ 88 \times 1 \times 2^{1} + \\ 88 \times 0 \times 2^{2} + \\ 88 \times 0 \times 2^{3} + \\ 88 \times 0 \times 2^{4} + \\ 88 \times 1 \times 2^{5} + \\ 88 \times 1 \times 2^{6} 88×99=88×1100011(2)88×1×20+88×1×21+88×0×22+88×0×23+88×0×24+88×1×25+88×1×26
代码:
int main()
{
int a = 88;
int b = 99;
int ans = 0;
for(;b;b >>= 1,a <<= 1)
ans += a * (b & 1);
cout << ans;
return 0;
}
怎么样,是不是相当简洁?
快速幂
道理也相同对于幂指式 a b a^{b} ab,我们把 b b b拆成二进制,然后根据同底数相乘底数不变指数相乘的道理,把 a b a^{b} ab拆成 a 2 n 1 × … × a 2 n k a^{2^{n_{1}}} \times \ldots \times a^{2^{n_{k}}} a2n1×…×a2nk这种指数是 2 2 2的幂次乘积的形式。
例如:
3 7 = 3 10 0 2 × 3 1 0 2 × 3 1 2 = 3 4 × 3 2 × 3 1 3^{7} = 3^{100_{2}} \times 3^{10_{2}} \times 3^{1_{2}} = 3^{4} \times 3^{2} \times 3^{1} 37=31002×3102×312=34×32×31
代码:
int main()
{
int a = 3;
int b = 7;
int ans = 1;
for(;b;b >>= 1,a *= a)
{
if(b & 1) ans *= a;
}
cout << ans;
return 0;
}
总结
以上两种快速运算的方式都运用了二进制的思想,有一定的相同之处。