最大公约数、同余原理
最大公约数是能整除多个整数的最大数,常用欧几里得算法。同余原理判断两数除以同一数后余数是否相同,应用于数论和密码学。
最大公约数、同余原理
最大公约数
1
2
3
4
5
6
7
8
9
// 最大公约数,时间复杂度O((logn)^3)
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
// 最小公倍数
int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
878. 第 N 个神奇数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 最大公约数
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
// 最小公倍数
int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
const int MOD = 1e9 + 7;
int min(int a, int b) {
return a > b ? b : a;
}
int nthMagicalNumber(int n, int a, int b) {
// 计算最小公倍数
long long l = lcm(a, b);
// 第n个神奇数一定落在min{a,b}~n*min{a,b}中
long long left = min(a, b);
long long right = ((long long) n * min(a, b));
long long mid;
// 二分(找左边界)
while (left <= right) {
mid = left + ((right - left) >> 1);
// 1~mid包含的神奇数的个数
// (mid / a)个数可以被a整除,(mid / b)个数可以被b整除,但这中间可能会有重复
// (mid / l)为重复的个数
int count = (mid / a) + (mid / b) - (mid / l);
if (count >= n)
right = mid - 1;
else
left = mid + 1;
}
return left % MOD;
}
同余原理
- 加法、乘法每一步计算完后直接取模
- 减法则为
(a-b+mod)%mod
- 为确保过程中不溢出,乘法运算时的中间结果用long long保存
本文由作者按照 CC BY 4.0 进行授权