题面:a^b
快速幂思想:
每个正整数都可以唯一表示为若干指数不重复的
2
2
2 的次幂的和。
如果
b
b
b 在二进制表示下有
k
k
k 位,其中第
i
(
0
≤
i
<
k
)
i(0\leq i<k)
i(0≤i<k) 位的数字是
c
i
c_i
ci,那么有:
b
=
c
k
−
1
2
k
−
1
+
c
k
−
2
2
k
−
2
+
.
.
.
+
c
0
2
0
b=c_{k-1}2^{k-1} + c_{k-2}2^{k-2} +...+c_02^0
b=ck−12k−1+ck−22k−2+...+c020
所以:
a
b
=
a
c
k
−
1
2
k
−
1
∗
a
c
k
−
2
2
k
−
2
∗
.
.
.
∗
a
c
0
2
0
a^b=a^{c_{k-1}2^{k-1}}*a^{c_{k-2}2^{k-2}}*...*a^{c_{0}2^{0}}
ab=ack−12k−1∗ack−22k−2∗...∗ac020
因为
k
=
⌈
l
o
g
2
(
b
+
1
)
⌉
k=\lceil log_2(b+1)\rceil
k=⌈log2(b+1)⌉,所以上式乘积项的数量是小于等于
⌈
l
o
g
2
(
b
+
1
)
⌉
\lceil log_2(b+1)\rceil
⌈log2(b+1)⌉ 个的。
又有:
a
2
i
=
(
a
2
i
−
1
)
2
a^{2^i}=(a^{2^{i-1}})^2
a2i=(a2i−1)2
所以,可以通过
k
k
k 次递推就求出每一个乘积项。
当
c
i
=
1
c_i=1
ci=1, 即当
b
b
b 二进制的第
i
i
i 项不为
0
0
0 ,且乘积项不为
1
1
1 时,把该乘积项累乘到
a
n
s
ans
ans 中。
整个算法的时间复杂度为
O
(
l
o
g
2
b
)
O(log_2b)
O(log2b).
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int qmi(int a, int b, int mod)
{
int ans = 1 % mod;
while(b)
{
if(b & 1) ans = (LL)ans * a % mod;
a = (LL)a * a % mod;
b >>= 1;
}
return ans;
}
int main()
{
int a, b, p;
cin >> a >> b >> p;
cout << qmi(a, b, p) << endl;
return 0;
}