LeetCode878. 第 N 個神奇數字(java)

sayWhat_sayHello發表於2018-11-28

題目

https://leetcode-cn.com/problems/nth-magical-number/description/

思路

這題我首先覺得這個模的數怎麼這麼奇怪,然後查了一下說,這個是int裡最大的質數~那麼肯定和題目無關了。

如果按最簡單的思路就是一個個加上去試的話目測會超時,因為如果N,A,B都取最大值,那就是要加到40000*10^9!!

先從A = 2,B = 3找規律:
以A = 2,B = 3為例,隨著N遞增有 2,3,4(22),6(A,B的最小公倍數),8(24),9(3*3)…

然後(嗯!要有點靈感)就發現 假設最後的值為 res ,此時個數 N = res/A + res/B - res/(A,B的最小公倍數)

那麼當對於一個數k來說它的 個數k 如果小於N,那麼res肯定在它的右邊,否則在它的左邊。這裡我們再用2分的方式逼近res。

當k = N時,我們就命中了想要的那個數了,再對結果進行取模。

程式碼

import java.math.BigDecimal;
class Solution {
    public int nthMagicalNumber(int N, int A, int B) {
        /**
         * 假設最後的值為 res ,此時 N = res/A + res/B - res/(A,B的最小公倍數)
         * 以A = 2,B = 3為例,隨著N遞增有 2,3,4(2*2),6(A,B的最小公倍數),8(2*4),9(3*3)...
         */
        
        int g = A*B/gcd(A,B);//最小公倍數 = A*B / 最大公約數
        
        long min = 0;
        long max = 40000000000000L;
        
        while(min < max){
            long mid = min + ((max - min) / 2);    
            long temp = mid / A + mid / B - mid / g;
            
            if(temp < N){
                min = mid + 1;
            }else {
                max = mid;
            }
        }
        return (int)(max % 1000000007);   
    }
    
    public int gcd(int a,int b){
        return b == 0 ? a : gcd(b,a%b);
    }
}

相關文章