移位运算例题
求 a 的 b 次方对 p 取模的值 , 其中 1 ≤ a , b , p ≤ 1 0 9 求a的b次方对p取模的值,其中1 \le a,b,p \le 10^9 求a的b次方对p取模的值,其中1≤a,b,p≤109
思路
根据数学常识,每个正整数可以唯一标识为若干指数不重复的
2
2
2的次幂的和。
也就是说,如果
b
b
b在二进制表示下有
k
k
k位,其中第
i
(
0
≤
i
<
k
)
i(0\le 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}+\cdots+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}}+\cdots+a^{c_02^0}
ab=ack−1∗2k−1+ack−2∗2k−2+⋯+ac020
因为
k
=
[
l
o
n
g
2
(
b
+
1
)
]
k=[long_2(b+1)]
k=[long2(b+1)](其中[ ]表示向上取整),所以上市乘积项的数量不多于
[
l
o
g
2
(
b
+
1
)
]
[log_2(b+1)]
[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
&
1
b\&1
b&1运算可以取出
b
b
b在二进制下的最低位,而
b
>
>
1
b>>1
b>>1运算可以舍去最低位,在递推的过程中将二者结合,就可以遍历
b
b
b在二进制表示下的所有数位
c
i
c_i
ci。整个算法的时间复杂度为
O
(
log
2
b
)
O( \log _2b)
O(log2b)
代码
//calculate (a^b)modp
int power(int a, int b, int p)
{
int ans = 1%p;
for(;b;b>>=1)
{
if(b&1)
ans = (long long)ans*a%p;
a = (long long)a*a%p;
}
return ans;
}
注意
若变量超出longlong的存储类型时,可以参考以下解决办法算法进阶——64位整数乘法