文章

最大公约数、同余原理

最大公约数是能整除多个整数的最大数,常用欧几里得算法。同余原理判断两数除以同一数后余数是否相同,应用于数论和密码学。

最大公约数、同余原理

最大公约数

1
2
3
4
5
6
7
8
9
// 最大公约数,时间复杂度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 个神奇数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 最大公约数
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保存
本文由作者按照 CC BY 4.0 进行授权