a ^ b
题目大意
在 a a a 的 b b b 次方对 p p p 取模,其中 1 ≤ a , b , p ≤ 1 0 9 1 \leq a,b,p \leq 10 ^ 9 1≤a,b,p≤109
思路
根据数学常识,每一个正整数都可以为一的表示为若干指数不重复的 2 2 2 的次幂的和。 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。 c i c_i ci 表示在二进制下 b b b 的第 i i i 位是 0 0 0 还是 1 1 1。
时间复杂度
因为 k = ⌈ l o g ( b + 1 ) ⌉ k = \lceil log(b + 1) \rceil k=⌈log(b+1)⌉ ,通过 k k k 次递推出每一个乘积项,因此整个算法的时间复杂度为 l o g 2 b log_2b log2b。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
pair<string,int> a[N];
int m,n;
int main()
{
int a,b,p;
cin >> a >> b >> p;
LL ans = 1 % p;
for( ; b; b >>= 1){
if(b & 1){
ans = (LL)ans * a % p;// a ^ b
}
a = (LL)a * a % p;
}
cout << ans << endl;
return 0;
}
64位整数乘法
题目大意
求 a a a 乘 b b b 对 p p p 的取模,其中 1 ≤ a , b , p ≤ 1 0 18 1 \leq a,b,p \leq 10 ^ {18} 1≤a,b,p≤1018
解法 1 1 1
思路
类似于快速幂的思想,把整数 b b b 用二进制表示, 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 + c k − 2 2 k − 2 + … … + c 0 2 0 ) a * b = a * (c_{k-1}2^{k-1} + c_{k-2}2^{k-2} + …… + c_02^0) a∗b=a∗(ck−12k−1+ck−22k−2+……+c020)。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
pair<string,int> a[N];
int m,n;
int main()
{
LL a,b,p;
cin >> a >> b >> p;
LL ans = 0;
for(; b; b >>= 1){
if(b & 1){
ans = (ans + a) % p;
}
a = a * 2 % p;
}
cout << ans << endl;
return 0;
}
解法 2 2 2
思路
利用 a ∗ b a * b a∗b mod p p p = a ∗ b a * b a∗b - ⌊ a ∗ b / p ⌋ ∗ p \lfloor a * b / p \rfloor * p ⌊a∗b/p⌋∗p。在 a ∗ b / p a * b / p a∗b/p 中我们可以用浮点数来执行,因为浮点数的在十进制下的有效数字有 18 、 19 18 、 19 18、19 位 ( 因为相除之后会变成小数点后的位数,足够存储 ) (因为相除之后会变成小数点后的位数,足够存储) (因为相除之后会变成小数点后的位数,足够存储),足够胜任。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
pair<string,int> a[N];
int m,n;
int main()
{
LL a,b,p;
cin >> a >> b >> p;
a %= p,b %= p;
LL c = (long double)a * b / p;
LL ans = a * b - c * p;
if(ans < 0) ans += p;
else if(ans >= p)ans -= p;
cout << ans << endl;
return 0;
}