快速加,快速乘,快速幂的原理和函数表示

先讲个故事:
论如何教一个一年级小朋友(只会100以内的加减法)计算:(保证给出的不超过40)
①35+35+33
②24×26
③125
第一个加法。直接加超过100了,不会做。所以我们告诉他,每一次加出来的结果,要是超过了40就减40。那么过程如下,第一步:35+35=70>40,所以70-40=30;第二步:30+33=63>40,所以63-40=23。算出我们要的(当mod=40)答案是23。
35+35+33
=70+33
=30+33
=63
=23
第二个乘法(乘法变加法 24+24+24… 固然可以,但是速度跟不上)。
26拆开成2×13,原式=24×2×13,先算24×2=24+24=(24+24)%40=8,原式=8×13=8×(1+12)=8+8×12,先算乘法再加。8×12=8×2×6=16×6=32×3=32×(1+2)=32+32×2=32+24=16。加上刚才的8等于24。将乘法×2或者是加法,对于每一步加法都%40。
24×26(以下加法和×2的乘法,自动%40)
=24×2×13
=8×13
=8+8×12
=8+8×2×6
=8+16×6
=8+16×2×3
=8+32×3
=8+32+32×2
=8+32+24
=0+24
=24
第三个幂运算。125=124×12=(122)2×12,使用第二步的乘法计算出122也就是12×12的结果为24,然后242×12,计算24×24的结果,然后×12就行了。
125(以下乘法和2的幂运算,自动%40)
12×124
=12×(122)2
=12×242
=12×16
=32


以下正文。。
在做算法题的时候,偶然碰到了几次大数相加,相乘的计算,当时不会做,所以特意去了解了一下,顺便写下来记录一下。
使用快速加,快速乘,快速幂的原因:计算的结果超过了变量的表示范围。就int型的数来说,它的范围是 -231~231-1,即-2147483648——2147483647。那么当

int a=2147483647,b=2147483647,c;
c=a+b;	//此时的c=-2

俩个大的数相加得不到我们想要的结果。因为int位数的限制,4字节也就是32位,超过32位的就会舍去,或者说进行了一下模运算(a+b)%232
在题目里看到一串很长的数,然后还要进行乘法运算,这时候万能的long long也装不下啊。ps. long long是263-1,差不多就是1后面18个0多一点。
这时候题目中一般都会有一个mod,用来限制数变的太大,如果没有就视情况自己找一个。
打个比方,计算机就是个比较笨的小朋友,它只能做一些结果不超过231的计算,而快速加,乘,幂 就是教会这个小朋友在一定条件下计算出想要的结果。

对于文章开头我们已经教会了一个只会100内加法的小朋友。整理一下就是,快速加(a+b+c)=每次加法结果%40;快速乘(a×b)=b是偶数就a×2×b/2,b是奇数就变成乘a+a×(b-1)的加法;快速幂(ab)=b是偶数即(a×a)b/2,b是奇数就变成a×(a×a)b/2的乘法。
实际做题的时候,在离int最大值很远的地方就设置mod,让数值控制在我们想要的范围。写成代码就是这样


int quickadd(int a, int b, int mod)
{
 //返回相加的结果模mod
 return (a + b) % mod;
}
int quickmul(int a, int b, int mod)
{
 if (b == 0)
  //设置迭代结束条件,当b=1再迭代一次就=0了
  return 0;
 if (b % 2 == 0)
  //偶数就让a*2 乘b/2
  return quickmul((a * 2) % mod, b / 2, mod);
 else
  //奇数就等于a 加 a*(b-1)
  return (a + (quickmul(a, b - 1, mod))) % mod;
}
int quickpower(int a, int b, int mod)
{
 if (b == 0)
  //设置迭代结束条件
  return 1;
 if (b % 2 == 0)
  //偶数就让a*a 幂b/2
  return quickpower(quickmul(a, a, mod), b / 2, mod);
 else
  //奇数就等于a 乘 a^(b-1)
  return quickmul(a, quickpower(a, b - 1, mod), mod);
}

补充一下,更完美的写法


int quick_mul(int a, int b, int mod)
{
 int res = 0;
 while (b != 0)
 {
  if (b & 1)
   res = (res + a) % mod;
  b = b >> 1;
  a = (a * 2) % mod;
 }
 return res;
}
int quick_power(int a, int b, int mod)
{
 int res = 1;
 while (b != 0)
 {
  if (b & 1)
   res = quick_mul(res, a, mod);
  b = b >> 1;
  a = quick_mul(a, a, mod);
 }
 return res;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值