一个正整数如果能被 a
或 b
整除,那么它是神奇的。
给定三个整数 n
, a
, b
,返回第 n
个神奇的数字。因为答案可能很大,所以返回答案 对 109 + 7
取模 后的值。
示例 1:
输入:n = 1, a = 2, b = 3 输出:2
示例 2:
输入:n = 4, a = 2, b = 3 输出:6
提示:
1 <= n <= 109
2 <= a, b <= 4 * 104
Related Topics
- 数学
- 二分查找
著书三年倦写字,如今翻书不识志,若知倦书悔前程 ,无如渔樵未识时
一个正整数如果能被 a
或 b
整除,那么它是神奇的。
给定三个整数 n
, a
, b
,返回第 n
个神奇的数字。因为答案可能很大,所以返回答案 对 109 + 7
取模 后的值。
示例 1:
输入:n = 1, a = 2, b = 3 输出:2
示例 2:
输入:n = 4, a = 2, b = 3 输出:6
提示:
1 <= n <= 109
2 <= a, b <= 4 * 104
二分查找,最大公约数,最小公倍数
三个必要知识
gcd(long a, long b)
求最大公约数 辗转相除法,lcm(long a, long b)
求最小公倍数,
二分查找
从简单情况说起,设有一个数字i
,从1
到i
过程中能整除a
的数字有i/a
个
那么同样的能整除b
的数字有i/b
个
能同时整除a
和b
的数字有i/lcm(a, b)
个,lcm(a, b)
为a``b
的最小公倍数,
那么我们就可以知道,数字n
以下,符合题意的数字有n/a + n/b - n/lcm(a,b)
个,需要减去多计数一遍的最小公倍数个数
那么接下来就是用二分法来找到这个恰好能符合题意的数字
class Solution {
public int nthMagicalNumber(int n, int a, int b) {
long mod = (long)(1e9 + 7);
long l = 2;
long r = (long) n * Math.min(a,b);
while (l < r){
long mid = l + ((r-l)>>1);
if(f(a,b,mid) < n){
l = mid + 1;
}else{
r = mid;
}
}
return (int)(l % mod);
}
long gcd(long a, long b) {
return b == 0 ? a : gcd(b, a % b);
}
long lcm(long a, long b) {
return (a * b) / gcd(a, b);
}
long f(long a, long b, long x) {
return (x / a) + (x / b) - (x / lcm(a, b));
}
}
发表评论