因为计算机算加法的时间比算乘法的时间快得多(这貌似是学汇编才能明白原因?反正我不懂)所以我们如果能把乘法尽可能的用加法达到同样的效果,就可以缩短计算时间
我们知道,任何一个数(这里指正整数)都可以用二进制表示,所以如果把一个数拆分成他的二进制就是一堆0和1:
例如:8(D)=1000(B)
16(D) = 10000(B)
书面约定可以用字母来表示数字的对应进制
D 十进制
B 二进制
O 八进制
H 十六进制
这里就需要明白权重的概念了:
举例子来说:
532(D)有三个数字5和3和2,每一位数字所代表的含义是不同的,2在个位,就代表他是2个1,3代表3个10,5代表5个100,很好理解对不对
那么类比一下,532(D)=1000010100(B),一共有一堆0和三个1,从右往左数第一个1代表1个2*2,也就是1个2^2,(至于为什么他是从右往左数第三个数字权重确实2的2次方呢?因为从右往左数第一个数字代表的是1,也就是2的0次方。)第二个1代表1个2的4次方,第三个就代表了1个2的九次方
所以532 = 22+24+29
那么我们可以考虑用三个2次方的数来代替532去进行乘法计算
既然如此,快速乘的思想如下:
1、把乘法的其中一个数变成二进制
2、然后把1所在的权重搞清楚
3、不断把结果累加,最后得出结果
先实现第一步:变成二进制;
我们把除余的救国倒过来,就得到了100010100(B)
于是第一步代码就清晰了
while(b){
if(b%2==1)
{
res=res+a;//加上结果
}
a是个啥?,就是第二步要解决的权重问题
从表格我们容易想到,不管现在是不是1,我的权重必须跟着变化,也就是说,权重的变化是在if值外的,与是不是满足if无关
while(b){
if(b&1)
res=res+a;
a=a+a;//每次权重都是上一个权重的2倍
b/=2;
}
以上就是快速乘的核心部分,完整的代码如下
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ab_addc(ll a,ll b)
{
ll res=0;//这里是0,快速幂是1
while(b){
if(b&1)//位运算
res=res+a;//这里是加,快速幂是乘
a=a+a;
b>>=1;//效果等价与/=2
}
return res;
}
int main()
{
ll a,b;
while(cin >> a >> b){
ll MOD = ab_addc(a,b);
printf("%lld\n",MOD);
}
}