快速幂

问题描述:求A^B的最后三位数表示的整数
说明:A^B的含义是A的B次方

什么是快速幂

这个题目看起来很简单,貌似A^B%1000就能得到答案,但真的是这样吗?
如果按上述方法,当A=2,B=100时,2^100%1000得到却是0,这就有问题了。
因此,如果题目让你求2的100次方,貌似我们程序设计语言中最大的long lnog类型也无法承载这么大的数值,所以题目才不会要求你输出结果,因为结果可能会非常的大,大到没有任何类型可以承载。所以我们会发现上面的结果为什么是0,因为已经发生溢出了。
那为什么题目要求输出结果的最后三位数表示的整数呢?有的同学可能会问:求一个数的最后三位数表示的整数好办,只要用这个结果进行“取模”运算,让其对1000取模,得到的数就是这个数最后三位数表示的整数。(例如:12345的最后三位数表示的整数是:12345%1000=345)。但是,你这结果都无法求出来,让我怎么进行“取模”运算呢?你这不是瞎闹吗?

这就要用到快速幂了,时间复杂度为O(logn)。
假设我们已知 2^3 求 2^6,不就是 2^3 * 2^3嘛。快速幂就是这个原理。
那如果遇到奇数怎么办?2 ^ 5?
那不就是 2 * 2 ^ 4 这不就成了嘛。
所以这就是快速幂的基本思路求a ^ b

1)当b是奇数时,那么有 a^b = a * a^*(b-1)
2)当b是偶数时,那么有 a^b = a^(b/2) * a^(b/2)

举个例子?2 ^10

2^10 = 2^5 * 2^5
2^5 = 2 * 2^4
2^4 = 2^2 * 2^2
2^2 = 2^1 * 2^1
2^1 = 2 * 2^0

快速幂的递归写法

typedef long long ll;
ll binaryPow(ll a,ll b,ll m)
{
    if(!b)return 1;
    else if(b&1)return a*binaryPow(a,b-1,m)%m;
    else
    {
        ll num=binaryPow(a,b/2,m);
        return num*num%m;
    }
}

快速幂的迭代写法
对于 a ^ b来说,若果把 b 写成2 进制,那么b 就可以写成若干二次幂之和,如13 的二进制 1101,于是3 号位 、2号位、0号位就都是1,那么就可以得到13 = 2^3 + 2^2 + 2^1 = 8 + 4 + 1。所以a ^13 = a^8 * a^4 * a^1。
具体步骤。
(1)初始令ans = 1,用来存放累积的结果。
(2)判断b的二进制末尾是否为1 ,(及判断 b&1 是否为 1),也可以理解为判断b 是否为奇数。如果是的话,令ans乘上a的值。
(3)令a平方,并使b右移一位(也可以理解为,a^b 等于a的平方的b/2次方)。
(4)只要b 大于0,就返回(2)。

#include <iostream>
using namespace std;
typedef long long ll;
ll binaryPow(ll a,ll b,ll m)
{
    ll ans=1;
    while(b>0)
    {
        if(b&1)ans=ans*a%m;
        a=a*a%m;
        b>>=1;//b=b/2;
    }
    return ans;
}
int main()
{
    int a,b,m=1000;
    cin>>a>>b;
    cout<<binaryPow(a,b,m)<<endl;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值