快速幂
什么是快速幂算法呢?
假设现在要你求A的B次方,你的想法是什么?是不是用一个for循环,那么这个时间复杂度是多少呢?很明显这个时间复杂度是O(
n
n
n),那么我们有没有一种方法将这个时间复杂度降低呢?
答案是有的!
那么接下来我们看下面这题
题目描述
求 a的 b次方对 p取模的值。
输入格式
三个整数 a,b,p在同一行用空格隔开。
输出格式
输出一个整数,表示
a
b
a^b
ab %p的值。
数据范围
0
≤
a
,
b
≤
1
0
9
0 \leq a,b \leq10^9
0≤a,b≤109
1
≤
p
≤
1
0
9
1 \leq p \leq 10^9
1≤p≤109
输入样例
3 2 7
输出样例
2
整体的代码如下
#include<iostream>
using namespace std;
int main()
{
int a,b,mod;
cin>>a>>b>>mod;
int res=1%mod;
while(b)
{
if(b&1)
res=res*1ll*a%mod;
a=a*1ll*a%mod;
b>>=1;
}
cout<<res<<endl;
return 0;
}
思路
本题要求的是
a
b
a^b
ab mod p的值,所以这里以
2
10
2^{10}
210 mod 66来举例子。
我们都知道十进制的10转化为二进制为
(
1010
)
2
(1010)_2
(1010)2,所以我们这里的
2
10
2^{10}
210 可以表示成为
2
1010
2^{1010}
21010,(注意这里的右上角的角标是二进制的),同时也可以表示成为
2
1000
2^{1000}
21000 *
2
000
2^{000}
2000 *
2
10
2^{10}
210 *
2
0
2^{0}
20,(注意这里右上角的角标仍然为二进制),转化为十进制之后为
2
2
3
2^{2^{3}}
223 *
2
2
0
2^{2^{0}}
220 *
2
2
1
2^{2^{1}}
221 *
2
2
0
2^{2^{0}}
220,这里我们可以发现右上角的角标和二进制的该位有关,如果二进制该为为0,则右上角的角标为0,如果二进制的该位不为0,则右上角的角标为该为所在的序号(从右往左数),最后将每一位都相乘就得出最后的结果,这个时间复杂度我们很容易分析出来是
O
(
l
o
g
2
b
)
O(log_2b)
O(log2b)。
至此所有的解析完毕。