Be a plurality of n-th request number divisible

leet code 1201. Ugly Number III.

Write a program to find the n-th ugly number.

Ugly numbers are positive integers which are divisible by a or b or c.

Example 1:

Input: n = 3, a = 2, b = 3, c = 5
Output: 4
Explanation: The ugly numbers are 2, 3, 4, 5, 6, 8, 9, 10... The 3rd is 4.

Example 2:

Input: n = 4, a = 2, b = 3, c = 4
Output: 6
Explanation: The ugly numbers are 2, 3, 4, 6, 8, 9, 12... The 4th is 6.

Example 3:

Input: n = 5, a = 2, b = 11, c = 13
Output: 10
Explanation: The ugly numbers are 2, 4, 6, 8, 10, 11, 12, 13... The 5th is 10.

Example 4:

INPUT: = n-1000000000, A = 2, B = 217 983 653, 336 916 467 C = 
the Output: 1999999984 
Reference:
[. 1] leetcode at discuss: https://leetcode.com/problems/ugly-number-iii/discuss/387539/cpp- Search-with--Binary Picture-Binary-Search-and-Template
[2] Euclidean algorithm greatest common divisor: https://www.cnblogs.com/kirito-c/p/6910912.html (given the error codes gcd)
entitled: seeking can be a positive integer of n a or b or c divisible.
Translation: seeking argmin_N F (N), F ( N) = a or b, or c can be divisible, less than N, the counted number, F (N) == n
further, so that f (a) = be number less than N number divisible by a similar f (b), f (c ). So that G (a, b) a, b, the least common multiple.
Title then becomes: argmin_N F (N), F (N) = f (a) + f (b) + f (c) - f (g (a, b)) - f (g (a, c)) - f (g (b, c )) + f (g (a, b, c)), F (N) == n
Pirates a diagram to explain: a = f (a), b = f (b) and the like.

 

 

 

 In this case involves two questions:

F 1. find how the number less than N can be a number divisible by (a)?

2. how find the least common multiple of a and b g (a, b)?

A: 1. N / a, that can be a number divisible by all may be expressed as p * a, p is a positive integer. All less than the number N is expressed as a value capable of f (a) of p * a number, and the value of p from 1 to N / a. Therefore, the answer is N / a

2. The least common multiple calculated as a * b / a and b the greatest common divisor. The greatest common divisor by the Euclidean algorithm can be, that is, Euclidean algorithm to solve.

Generally understood as follows: If there is a large number of small and a number b, if a% b == 0, then b is the greatest common divisor of a and b.

! If a% b = 0, assuming a = q * b + r, r is the remainder, and a = s * t, b = u * t, t is a divisor of a and b, there is r = (s - q * u) * t, t is a divisor of the number indicates that the remainder a and b. Therefore, the greatest common divisor of b and r is the greatest common divisor of a and b. Such recursion, at a time when the remainder is 0, the divisor is the greatest common divisor.

Code can be written as:

    int gcd(int a, int b){
        int r = 0;
        while (b){
            r = a % b;
            a = b;
            b = r;
        }
        return a;
    }

After obtaining the calculated f and g, can find the condition of minimum N F (N) == n of the. It can be seen F (N) is a monotonic function, i.e., if M> = N, there are F (M)> = F (N).

This is similar to the index to find the value of n elements in an ordered array. F (N) is an array, N is its index. Therefore, you can use binary search.

insomniacat  provides the basic framework for the binary search:

while(lo < hi) {
int mid = lo + (hi - lo) / 2;
if(Special condition passed)(optional):
	return mid; 
if(condition passed)
  hi = mid;
else 
  lo = mid + 1;
}
return lo;

 

The final code:

class Solution {
public:
    int nthUglyNumber(int n, int a, int b, int c) {
        int lo = 1, hi = 2 * (int)1e9;
        long A = a, B = b, C = c;
        long AB = A * B / gcd(A, B);
        long AC = A * C / gcd(A, C);
        long BC = B * C / gcd(B, C);
        long ABC = A * BC / gcd(A, BC);
        while (lo < hi){
            int mid = (hi - lo) / 2 + lo;
            // compute F(N)
            long FN = mid / A + mid / B + mid / C - mid / AB - mid / AC - mid / BC + mid / ABC;
            if (FN < n)
                lo = mid + 1;
            else
                hi = mid;
        }
        return lo;
    }
    
    int gcd(long a, long b){
        int r;
        while (b){
            r = a % b;
            a = b;
            b = r;
        }
        return a;
    }
};

  

Guess you like

Origin www.cnblogs.com/vimery/p/11569723.html