题目描述
求 a a a 的 b b b 次方对 p p p 取模的值。
输入格式
三个整数 a , b , p a,b,p a,b,p,在同一行用空格隔开。
输出格式
输出一个整数,表示 a^b mod p
的值。
数据范围
0 ≤ a , b ≤ 1 0 9 0≤a,b≤10^9 0≤a,b≤109,
1 ≤ p ≤ 1 0 9 1≤p≤10^9 1≤p≤109
输入样例
3 2 7
输出样例
2
题目分析
快速幂。根据二进制, 如 b b b 在二进制表示下有 k k k 位,其中第 i ( 0 ≤ i ≤ k ) i (0\le i \le k) i(0≤i≤k) 位的数字是 c i c_i ci,那么 b = c k − 1 2 k − 1 + c k − 1 2 k − 2 + … + c 0 2 0 b=c_{k-1}2^{k-1}+c_{k-1}2^{k-2}+… +c_02^0 b=ck−12k−1+ck−12k−2+…+c020。因此, a b = a c k − 1 2 k − 1 ∗ a c k − 1 2 k − 2 ∗ … ∗ a c 0 2 0 a^b=a^{c_{k-1}2^{k-1}}*a^{c_{k-1}2^{k-2}}*… *a^{c_02^0} ab=ack−12k−1∗ack−12k−2∗…∗ac020。又 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 时将这一项乘入结果中,时间复杂度 O ( k ) = O ( l o g b ) O(k)=O(logb) O(k)=O(logb)。
代码:
int power(int a, int b, int p){
if (p == 1) return 0; //特判
int res = 1;
while (b){
if (b & 1) res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}
题目描述
求 a a a 乘 b b b 对 p p p 取模的值。
输入格式
第一行输入整数 a a a,第二行输入整数 b b b,第三行输入整数 p p p。
输出格式
输出一个整数,表示 a*b mod p
的值。
数据范围
1 ≤ a , b , p ≤ 1 0 18 1≤a,b,p≤10^{18} 1≤a,b,p≤1018
输入样例
3
4
5
输出样例:
2
题目分析
龟速乘。与上题快速幂的思想类似, 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 a∗b=a∗ck−1∗2k−1+a∗ck−2∗2k−2+…+a∗c0∗20。 k k k 次递推求出每个成积项,如果 c i = 1 c_i=1 ci=1 就将其加入结果中,时间复杂度 O ( l o g b ) O(logb) O(logb)。该方法可以保证运算过程中long long
不会溢出。
代码:
long long mul(long long a, long long b, long long p){
long long res = 0;
while (b){
if (b & 1) res = (res + a) % p;
a = a * 2 % p;
b >>= 1;
}
return res;
}