传送门: 第N个神奇的数字 – 困难
题目:
一个正整数如果能被 a 或 b 整除,那么它是神奇的。
给定三个整数 n , a , b ,返回第 n 个神奇的数字。因为答案可能很大,所以返回答案 对 10^9 + 7 取模 后的值。
输入输出示例:
示例 1:
输入:n = 1, a = 2, b = 3
输出:2
示例 2:
输入:n = 4, a = 2, b = 3
输出:6
数据范围:
- 1 < = n < = 1 0 9 1<=n<=10^9 1<=n<=109
- 2 < = a , b < = 4 ∗ 1 0 4 2<=a,b<=4*10^4 2<=a,b<=4∗104
解题思路:
手动模拟几个样例之后,会发现每当到达 a a a 和 b b b 的最小公倍数的倍数时, a a a 和 b b b 各会产生 l c m ( a , b ) a \frac {lcm(a,b)}{a} alcm(a,b) 和 l c m ( a , b ) b \frac {lcm(a,b)}{b} blcm(a,b) 个不同的数,唯独 l c m ( a , b ) lcm(a,b) lcm(a,b) 是 相同的,这样就能找到一个循环节,找到循环节之后,剩下的事情就是进行简单的计算和判断即可。
AC代码:
class Solution {
public:
long long mo = 1e9 + 7;
int nthMagicalNumber(int n, int a, int b) {
int gcd = __gcd(a,b),lcm = a * b / gcd;
//每个循环节中,a这边会产生 lcm / a - 1 个 不同的数,b这边会产生 lcm / b 的不同的数
int f1 = lcm / a - 1,f2 = lcm / b;
//一共会产生cnt个循环节,剩下dis个数
long long cnt = 1LL * n / (f1 + f2),dis = 1LL * n % (f1 + f2);
long long ans = cnt * lcm % mo;
long long l = 1,r = 1,pos = 1,now = 0;
//对于剩下的dis个数,循环判断到达第几个数结束
while(pos <= dis){
if(l * a < r * b)l ++,now = 0;
else r ++,now = 1;
pos ++;
}
if(now == 0){
l --;
ans = (ans + l * a % mo) % mo;
}else{
r --;
ans = (ans + r * b % mo) % mo;
}
return ans;
}
};
执行用时: 0 ms
内存消耗: 5.7 MB