最大公约数、同余原理

最大公约数

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

878. 第 N 个神奇数字

// 最大公约数
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保存
posted @ 2024-01-23 01:39  n1ce2cv  阅读(13)  评论(0编辑  收藏  举报