最大公约数
// 最大公约数,时间复杂度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;
}
// 最大公约数
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保存