数学专题2 -最大公约数和最小公倍数

最大公约数和最小公倍数

1. 基础概念

1.1 质数的定义

质数(Prime Number)是一个重要的数学概念,它的定义如下:

如果一个大于1的自然数只有1和它本身两个因数,那么这个数就被称为质数(或素数)。

换句话说,对于一个质数 p p p,它满足以下条件:

  1. p p p 是一个大于1的自然数;
  2. 如果 p p p 能被一个小于 p p p 且大于1的自然数整除,那么 p p p 就不是质数。

根据定义,我们可以得到一些质数的例子:

  • 2是最小的质数,因为它只有1和2两个因数;
  • 3、5、7、11、13、17、19等都是质数;
  • 4、6、8、9、10、12等都不是质数,因为它们除了1和本身之外,还有其他因数。

值得注意的是,1不是质数,因为质数的定义要求一个数必须大于1。同时,负整数和0也不是质数。

在数论中,质数有许多重要的性质和应用,例如:

  • 任何一个大于1的自然数都可以唯一地表示为质数的乘积(质因数分解);
  • 两个数的最大公约数可以通过它们的质因数分解求得;
  • 质数的分布有一定的规律,但至今没有一个简单的公式可以生成所有的质数。

理解质数的定义是学习数论的基础,在探索最大质因数和最小质因数时,我们会频繁用到质数的概念。

1.2 合数的定义

1.2 合数的定义

合数(Composite Number)是与质数相对的一个概念,它的定义如下:

如果一个大于1的自然数除了1和它本身之外,还有其他因数,那么这个数就被称为合数。

换句话说,对于一个合数 c c c,它满足以下条件:

  1. c c c 是一个大于1的自然数;
  2. 存在一个小于 c c c 且大于1的自然数 d d d,使得 d d d 能整除 c c c

根据定义,我们可以得到一些合数的例子:

  • 4是最小的合数,因为它有1、2和4三个因数;
  • 6、8、9、10、12、14、15、16等都是合数;
  • 2、3、5、7、11、13、17、19等都不是合数,因为它们只有1和本身两个因数。

值得注意的是,1既不是质数也不是合数,因为合数的定义要求一个数必须大于1。同时,负整数和0也不是合数。

质数和合数是互补的概念,它们构成了所有大于1的自然数的两个不相交的子集。换句话说:

  • 任何一个大于1的自然数要么是质数,要么是合数;
  • 没有一个数既是质数又是合数;
  • 1既不是质数也不是合数。

在学习最大质因数和最小质因数时,我们主要关注的是合数,因为质数只有1和本身两个因数,而合数的因数结构更加复杂,需要进行质因数分解等操作。

1.3 因数的定义

因数(Factor)是一个基本的数学概念,它描述了两个数之间的整除关系。因数的定义如下:

如果一个整数 a a a 能被另一个整数 b b b 整除,那么我们称 a a a b b b 的因数,也称 b b b a a a 的倍数。

换句话说,对于两个整数 a a a b b b,如果存在一个整数 k k k,使得 a × k = b a \times k = b a×k=b,那么我们说:

  • a a a b b b 的因数;
  • b b b a a a 的倍数;
  • b b b 能被 a a a 整除;
  • a a a 能整除 b b b

根据定义,我们可以得到一些因数的例子:

  • 1和6都是6的因数,因为 1 × 6 = 6 1 \times 6 = 6 1×6=6 2 × 3 = 6 2 \times 3 = 6 2×3=6;
  • 1、2、3、4、6、12都是12的因数;
  • 对于任意整数 a a a,1和 a a a 都是 a a a 的因数,因为 1 × a = a 1 \times a = a 1×a=a

值得注意的是,因数可以是正整数、负整数或者0:

  • 如果 a a a b b b 的因数,那么 − a -a a 也是 b b b 的因数,因为 ( − a ) × ( − k ) = b (-a) \times (-k) = b (a)×(k)=b;
  • 0是0的因数,因为 0 × k = 0 0 \times k = 0 0×k=0 对于任意整数 k k k 都成立;
  • 0不是其他任何非零整数的因数,因为 0 × k = 0 ≠ a 0 \times k = 0 \neq a 0×k=0=a 对于任意非零整数 a a a 和任意整数 k k k 都成立。

在学习最大质因数和最小质因数时,我们主要关注正整数的因数。对于一个合数,我们通常需要找到它的所有因数,或者找到它的质因数(即那些是质数的因数)。因数的概念是理解质因数分解的基础。

1.3.1 天秀的苹果

天秀有 n n n 个苹果,她想把这些苹果分成两部分,分别给她的朋友小红和小明。天秀希望小红和小明得到的苹果数量之差的绝对值尽可能小。

请你帮助天秀计算,她应该如何分配苹果,才能使得小红和小明得到的苹果数量之差的绝对值最小。

输入格式

输入一个正整数 n n n,表示天秀有 n n n 个苹果。

输出格式

输出一个整数,表示小红和小明得到的苹果数量之差的最小绝对值。

样例输入1

10

样例输出1

0

样例解释1

天秀可以将10个苹果平均分成两部分,小红和小明各得到5个苹果,它们的差的绝对值为0。

样例输入2

7

样例输出2

1

样例解释2

天秀可以将7个苹果分成3个和4个两部分,小红和小明分别得到3个和4个苹果,它们的差的绝对值为1。这是差的绝对值最小的分配方案。

数据范围

对于所有评测用例, 1 ≤ n ≤ 1 0 9 1 \leq n \leq 10^9 1n109

题目解析

这道题考查的是数论中的奇偶性知识。我们可以发现,当苹果数量为偶数时,可以平均分配,差的绝对值为0;当苹果数量为奇数时,差的绝对值至少为1。因此,答案就是苹果数量除以2的余数。

解题思路

  1. 观察题目,我们需要将苹果分成两部分,且两部分的差的绝对值尽可能小。

  2. 考虑苹果数量的奇偶性:

    • 如果苹果数量为偶数,我们可以将苹果平均分成两部分,每部分都有 n 2 \frac{n}{2} 2n 个苹果,此时差的绝对值为 0,这是最优解。
    • 如果苹果数量为奇数,我们无法平均分配。最优的分配方案是将苹果分成 n − 1 2 \frac{n-1}{2} 2n1 n + 1 2 \frac{n+1}{2} 2n+1 两部分,此时差的绝对值为 1,这是最小的差的绝对值。
  3. 综上所述,问题可以转化为判断苹果数量的奇偶性:

    • 如果苹果数量为偶数,答案为 0;
    • 如果苹果数量为奇数,答案为 1。
  4. 在代码实现中,我们可以使用取模运算符 % 来判断一个数是奇数还是偶数:

    • 如果一个数除以 2 的余数为 0,那么它是偶数;
    • 如果一个数除以 2 的余数为 1,那么它是奇数。
  5. 因此,我们可以将苹果数量 n n n 除以 2,并取余数作为答案。这就是这道题的解题思路。

这个解题思路的核心是利用了奇偶性的性质,将问题简化为判断苹果数量的奇偶性。通过取模运算,我们可以很容易地判断一个数是奇数还是偶数,从而得到答案。

C++解答

#include <iostream>using namespace std;int main() {int n;cin >> n;cout << n % 2 << endl;return 0;
}

这个C++解答的时间复杂度为 O ( 1 ) O(1) O(1),空间复杂度为 O ( 1 ) O(1) O(1)。我们只需要读入苹果数量 n n n,然后用取模运算符 % 计算 n n n 除以 2 的余数即可。当 n n n 为偶数时,余数为 0;当 n n n 为奇数时,余数为 1。这个余数就是小红和小明得到的苹果数量之差的最小绝对值。

1.3.2 天秀的因数个数

天秀有一个正整数 n n n,她想知道 n n n 有多少个正因数。

正整数 a a a 是正整数 b b b 的因数,当且仅当存在整数 k k k,使得 b = a × k b = a \times k b=a×k

请你帮助天秀计算 n n n 的正因数的个数。

输入格式

输入一个正整数 n n n

输出格式

输出一个整数,表示 n n n 的正因数的个数。

样例输入1

12

样例输出1

6

样例解释1

12 的正因数有 1、2、3、4、6、12,共有 6 个。

样例输入2

36

样例输出2

9

样例解释2

36 的正因数有 1、2、3、4、6、9、12、18、36,共有 9 个。

数据范围

对于所有评测用例, 1 ≤ n ≤ 1 0 6 1 \leq n \leq 10^6 1n106

解题思路

  1. 正整数 n n n 的正因数包括 1 和 n n n 本身,以及在区间 [ 2 , n ] [2, \sqrt{n}] [2,n ] 中所有能整除 n n n 的数及其对应的商。

  2. 我们可以遍历区间 [ 1 , n ] [1, \sqrt{n}] [1,n ] 中的所有整数 i i i:

    • 如果 i i i 能整除 n n n,那么 i i i n n n 的一个因数;
    • 如果 i ≠ n i \neq \sqrt{n} i=n ,那么 n i \frac{n}{i} in 也是 n n n 的一个因数。
  3. 我们用一个变量 c n t cnt cnt 来记录因数的个数,初始时 c n t = 0 cnt = 0 cnt=0:

    • 对于每个能整除 n n n i i i,将 c n t cnt cnt 增加 1;
    • 如果 i ≠ n i \neq \sqrt{n} i=n ,再将 c n t cnt cnt 增加 1。
  4. 最终,变量 c n t cnt cnt 的值就是 n n n 的正因数的个数。

C++解答

#include <iostream>
#include <cmath>using namespace std;int main() {int n;cin >> n;int cnt = 0;for (int i = 1; i <= sqrt(n); i++) {if (n % i == 0) {cnt++;if (i != n / i) {cnt++;}}}cout << cnt << endl;return 0;
}

这个C++解答的时间复杂度为 O ( n ) O(\sqrt{n}) O(n ),空间复杂度为 O ( 1 ) O(1) O(1)。我们通过遍历区间 [ 1 , n ] [1, \sqrt{n}] [1,n ] 中的所有整数,判断每个整数是否为 n n n 的因数,并统计因数的个数。由于一个数的因数总是成对出现(除了完全平方数),所以我们只需要遍历到 n \sqrt{n} n 即可。

1.3.3 天秀的完美数

天秀在学习完数的概念。一个正整数如果等于除它本身外的所有因数之和,就称为完美数。例如,6 就是一个完美数,因为 6 = 1 + 2 + 3。

现在,天秀想知道在给定的区间 [ l , r ] [l, r] [l,r] 内,有多少个完美数。

请你帮助天秀计算完美数的个数。

输入格式

输入两个正整数 l l l r r r,表示查询的区间。

输出格式

输出一个整数,表示区间 [ l , r ] [l, r] [l,r] 内完美数的个数。

样例输入1

1 10

样例输出1

1

样例解释1

在区间 [ 1 , 10 ] [1, 10] [1,10] 内,只有 6 是完美数。

样例输入2

1 100

样例输出2

2

样例解释2

在区间 [ 1 , 100 ] [1, 100] [1,100] 内,有两个完美数:6 和 28。

数据范围

对于所有评测用例, 1 ≤ l ≤ r ≤ 1 0 6 1 \leq l \leq r \leq 10^6 1lr106

解题思路

  1. 根据完美数的定义,我们可以判断一个数是否为完美数:

    • 遍历从 1 到 n \sqrt{n} n 的所有整数 i i i;
    • 如果 i i i n n n 的因数,就将 i i i n i \frac{n}{i} in 加到因数和中(注意要避免重复加);
    • 如果因数和等于 n n n,那么 n n n 就是完美数。
  2. 我们可以遍历区间 [ l , r ] [l, r] [l,r] 中的每个数,判断它是否为完美数,并统计完美数的个数。

  3. 为了优化时间复杂度,我们可以预处理出所有不超过 1 0 6 10^6 106 的完美数,然后在查询时直接判断区间内有多少个预处理出的完美数。

C++解答

#include <iostream>
#include <vector>
#include <cmath>using namespace std;const int MAXN = 1e6;vector<int> perfectNumbers;void init() {for (int n = 2; n <= MAXN; n++) {int sum = 1;for (int i = 2; i <= sqrt(n); i++) {if (n % i == 0) {sum += i;if (i != n / i) {sum += n / i;}}}if (sum == n) {perfectNumbers.push_back(n);}}
}int main() {init();int l, r;cin >> l >> r;int cnt = 0;for (int num : perfectNumbers) {if (l <= num && num <= r) {cnt++;}}cout << cnt << endl;return 0;
}

这个C++解答的时间复杂度为 O ( M A X N × M A X N + q ) O(\sqrt{MAXN} \times MAXN + q) O(MAXN ×MAXN+q),空间复杂度为 O ( M A X N ) O(MAXN) O(MAXN),其中 q q q 是完美数的个数。我们首先预处理出所有不超过 1 0 6 10^6 106 的完美数,然后在查询时遍历预处理出的完美数,判断它们是否在查询区间内,并统计个数。预处理的时间复杂度为 O ( M A X N × M A X N ) O(\sqrt{MAXN} \times MAXN) O(MAXN ×MAXN),查询的时间复杂度为 O ( q ) O(q) O(q)。由于完美数非常稀少,所以实际运行时间很快。

1.3.4 天秀的因数平方和

天秀得到了一个正整数 n n n,她想知道 n n n 的所有因数(包括 1 1 1 n n n 本身)的平方和是多少。

例如,如果 n = 10 n = 10 n=10,那么它的因数有 1 , 2 , 5 , 10 1, 2, 5, 10 1,2,5,10,因数的平方和为 1 2 + 2 2 + 5 2 + 1 0 2 = 130 1^2 + 2^2 + 5^2 + 10^2 = 130 12+22+52+102=130

请你帮助天秀计算因数的平方和。

输入格式

输入一个正整数 n n n

输出格式

输出一个整数,表示 n n n 的所有因数的平方和。

样例输入1

10

样例输出1

130

样例解释1

10 10 10 的因数有 1 , 2 , 5 , 10 1, 2, 5, 10 1,2,5,10,因数的平方和为 1 2 + 2 2 + 5 2 + 1 0 2 = 130 1^2 + 2^2 + 5^2 + 10^2 = 130 12+22+52+102=130

样例输入2

25

样例输出2

651

样例解释2

25 25 25 的因数有 1 , 5 , 25 1, 5, 25 1,5,25,因数的平方和为 1 2 + 5 2 + 2 5 2 = 651 1^2 + 5^2 + 25^2 = 651 12+52+252=651

数据范围

对于 30 % 30\% 30% 的评测用例, 1 ≤ n ≤ 1 0 6 1 \leq n \leq 10^6 1n106;
对于 60 % 60\% 60% 的评测用例, 1 ≤ n ≤ 1 0 12 1 \leq n \leq 10^{12} 1n1012;
对于所有评测用例, 1 ≤ n ≤ 1 0 18 1 \leq n \leq 10^{18} 1n1018

解题思路

  1. 直接计算因数平方和的时间复杂度为 O ( n ) O(\sqrt{n}) O(n ),对于 n ≤ 1 0 18 n \leq 10^{18} n1018 的情况会超时。

  2. 我们可以利用因数的性质,通过分解质因数来计算因数平方和。设 n = p 1 a 1 × p 2 a 2 × . . . × p k a k n = p_1^{a_1} \times p_2^{a_2} \times ... \times p_k^{a_k} n=p1a1×p2a2×...×pkak,其中 p i p_i pi 为质因数, a i a_i ai 为对应的指数,那么 n n n 的因数平方和可以表示为:

    ∑ d ∣ n d 2 = ∏ i = 1 k ( 1 + p i 2 + p i 4 + . . . + p i 2 a i ) \displaystyle\sum_{d | n} d^2 = \prod_{i=1}^{k} (1 + p_i^2 + p_i^4 + ... + p_i^{2a_i}) dnd2=i=1k(1+pi2+pi4+...+pi2ai)

    其中 d ∣ n d | n dn 表示 d d d n n n 的因数。

  3. 对于每个质因数 p i p_i pi,我们可以计算出 1 + p i 2 + p i 4 + . . . + p i 2 a i 1 + p_i^2 + p_i^4 + ... + p_i^{2a_i} 1+pi2+pi4+...+pi2ai 的值,然后将所有质因数对应的值相乘,就得到了因数平方和。

  4. 为了快速分解质因数,我们可以使用预处理素数表的方法,然后在分解质因数时直接判断每个数是否为质数,并计算其指数。

C++解答

#include <iostream>
#include <vector>using namespace std;typedef long long ll;const int MAXN = 1e6;vector<int> primes;
bool isPrime[MAXN + 1];void sieve() {fill(isPrime, isPrime + MAXN + 1, true);isPrime[0] = isPrime[1] = false;for (int i = 2; i * i <= MAXN; i++) {if (isPrime[i]) {for (int j = i * i; j <= MAXN; j += i) {isPrime[j] = false;}}}for (int i = 2; i <= MAXN; i++) {if (isPrime[i]) {primes.push_back(i);}}
}ll power(ll x, ll exp) {ll result = 1;while (exp > 0) {if (exp & 1) {result *= x;}x *= x;exp >>= 1;}return result;
}ll solve(ll n) {ll result = 1;for (int p : primes) {if (p * p > n) {break;}if (n % p == 0) {ll exp = 0;while (n % p == 0) {n /= p;exp++;}result *= (power(p, 2 * exp + 2) - 1) / (p * p - 1);}}if (n > 1) {result *= (n * n + 1);}return result;
}int main() {sieve();ll n;cin >> n;ll ans = solve(n);cout << ans << endl;return 0;
}

这个C++解答的时间复杂度为 O ( M A X N + log ⁡ n ) O(\sqrt{MAXN} + \log n) O(MAXN +logn),空间复杂度为 O ( M A X N ) O(MAXN) O(MAXN)。我们首先预处理出所有不超过 1 0 6 10^6 106 的素数,然后在分解质因数时直接判断每个数是否为素数,并计算其指数。对于每个质因数,我们可以在 O ( 1 ) O(1) O(1) 的时间内计算出它对应的 1 + p i 2 + p i 4 + . . . + p i 2 a i 1 + p_i^2 + p_i^4 + ... + p_i^{2a_i} 1+pi2+pi4+...+pi2ai 的值,然后将所有质因数对应的值相乘,就得到了因数平方和。由于质因数的个数不超过 log ⁡ n \log n logn,所以分解质因数的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

需要注意的是,由于答案可能很大,所以我们需要使用 long long 类型来存储结果。同时,在计算指数时,我们可以使用快速幂算法来优化时间复杂度。

1.3.5 天秀的最大公因数

天秀有两个正整数 a a a b b b,她想知道它们的最大公因数是多少。

最大公因数(Greatest Common Divisor, GCD)是指两个或多个整数共有约数中最大的一个。例如,12 和 18 的最大公因数是 6。

请你帮助天秀计算最大公因数。

输入格式

输入两个正整数 a a a b b b

输出格式

输出一个整数,表示 a a a b b b 的最大公因数。

样例输入1

12 18

样例输出1

6

样例输入2

17 23

样例输出2

1

样例输入3

1024 2048

样例输出3

1024

样例输入4

123456 654321

样例输出4

3

样例输入5

1000000000 1

样例输出5

1

数据范围

  • 对于 30 % 30\% 30% 的数据, 1 ≤ a , b ≤ 1000 1 \leq a, b \leq 1000 1a,b1000;
  • 对于 60 % 60\% 60% 的数据, 1 ≤ a , b ≤ 1 0 6 1 \leq a, b \leq 10^6 1a,b106;
  • 对于 100 % 100\% 100% 的数据, 1 ≤ a , b ≤ 1 0 9 1 \leq a, b \leq 10^9 1a,b109

解题思路

  1. 计算最大公因数的经典算法是欧几里得算法(Euclidean algorithm)。欧几里得算法基于以下原理:

    • 如果 b = 0 b = 0 b=0,那么 gcd ⁡ ( a , b ) = a \gcd(a, b) = a gcd(a,b)=a;
    • 否则, gcd ⁡ ( a , b ) = gcd ⁡ ( b , a m o d b ) \gcd(a, b) = \gcd(b, a \bmod b) gcd(a,b)=gcd(b,amodb)
  2. 我们可以递归地应用欧几里得算法,直到 b = 0 b = 0 b=0 为止。此时, a a a 就是最大公因数。

  3. 在实现时,我们可以将欧几里得算法改写成迭代形式,避免递归调用的开销。

C++解答

#include <iostream>using namespace std;int gcd(int a, int b) {while (b != 0) {int temp = b;b = a % b;a = temp;}return a;
}int main() {int a, b;cin >> a >> b;int ans = gcd(a, b);cout << ans << endl;return 0;
}

这个C++解答的时间复杂度为 O ( log ⁡ ( min ⁡ ( a , b ) ) ) O(\log(\min(a, b))) O(log(min(a,b))),空间复杂度为 O ( 1 ) O(1) O(1)。欧几里得算法的迭代次数不超过 log ⁡ ( min ⁡ ( a , b ) ) \log(\min(a, b)) log(min(a,b)),因为每次迭代时,b 的值都会减小到 a % b,而 a % b 的值不会超过 a / 2

需要注意的是,在计算 a % b 时,如果 a < b,结果就是 a 本身。所以在迭代过程中,ab 的大小关系可能会发生变化,但这并不影响算法的正确性。

另外,样例5中给出了一个极端情况,当 ab 互质时,它们的最大公因数为1。这种情况下,欧几里得算法会在第一次迭代后就终止。

欧几里得算法是计算最大公因数的高效方法,它避免了直接枚举所有公因数的做法,时间复杂度较低。同时,它也是许多其他算法的基础,例如扩展欧几里得算法、求解线性丢番图方程等。

1.4 最大公约数和最小公倍数的定义

最大公约数(GCD)

两个或多个整数的公约数,是指同时整除这几个整数的整数。而最大公约数就是这些公约数里面最大的一个。

例如,12和18的公约数有1, 2, 3, 6,其中最大的是6,所以12和18的最大公约数是6。

如果几个整数的最大公约数是1,我们称这几个整数互质。

最小公倍数(LCM)

两个或多个整数的公倍数,是指同时被这几个整数整除的整数。而最小公倍数就是这些公倍数里面最小的一个。

例如,12和18的公倍数有36, 72, 108, …,其中最小的是36,所以12和18的最小公倍数是36。

最大公约数和最小公倍数的关系

对于两个整数a和b,它们的最大公约数记为gcd(a, b),最小公倍数记为lcm(a, b),那么它们满足以下关系:

a × b = g c d ( a , b ) × l c m ( a , b ) a \times b = gcd(a, b) \times lcm(a, b) a×b=gcd(a,b)×lcm(a,b)

换句话说,两个数的乘积等于它们的最大公约数与最小公倍数的乘积。这个性质在解题时非常有用。

求最大公约数的方法

求最大公约数有多种方法,最常用的是欧几里得算法,也叫辗转相除法。它的原理是:

g c d ( a , b ) = g c d ( b , a m o d b ) gcd(a, b) = gcd(b, a \bmod b) gcd(a,b)=gcd(b,amodb)

不断地对a和b进行取模运算,直到b为0为止,此时a就是最大公约数。

例如,求12和18的最大公约数的过程如下:

g c d ( 12 , 18 ) = g c d ( 18 , 12 ) = g c d ( 12 , 6 ) = g c d ( 6 , 0 ) = 6 gcd(12, 18) = gcd(18, 12) = gcd(12, 6) = gcd(6, 0) = 6 gcd(12,18)=gcd(18,12)=gcd(12,6)=gcd(6,0)=6

求最小公倍数的方法

有了最大公约数,求最小公倍数就简单了。根据上面提到的性质,我们有:

l c m ( a , b ) = a × b g c d ( a , b ) lcm(a, b) = \frac{a \times b}{gcd(a, b)} lcm(a,b)=gcd(a,b)a×b

所以,我们先求出最大公约数,然后用两数之积除以最大公约数,就得到了最小公倍数。

最大公约数和最小公倍数在数论中有许多应用,例如约分、求通分母、一次同余方程的求解等。熟练掌握它们的定义和求法,对解题很有帮助。

1.4.2 天秀的最小公倍数问题

天秀学习了最小公倍数的概念后,想要运用这个知识解决一些问题。

给定两个正整数 a a a b b b,请你帮助天秀计算它们的最小公倍数。

输入格式

输入两个正整数 a a a b b b

输出格式

输出一个整数,表示 a a a b b b 的最小公倍数。

样例输入1

3 5

样例输出1

15

样例输入2

12 18

样例输出2

36

样例输入3

1024 2048

样例输出3

2048

样例输入4

123456789 987654321

样例输出4

121932631112635269

样例输入5

1000000000 1

样例输出5

1000000000

数据范围

  • 对于 30 % 30\% 30% 的数据, 1 ≤ a , b ≤ 1000 1 \leq a, b \leq 1000 1a,b1000;
  • 对于 60 % 60\% 60% 的数据, 1 ≤ a , b ≤ 1 0 6 1 \leq a, b \leq 10^6 1a,b106;
  • 对于 100 % 100\% 100% 的数据, 1 ≤ a , b ≤ 1 0 9 1 \leq a, b \leq 10^9 1a,b109

题目解析

这道题考查的是最小公倍数的计算。我们知道,两个数的最小公倍数可以通过它们的最大公约数来计算。设 g c d ( a , b ) gcd(a, b) gcd(a,b) a a a b b b 的最大公约数,那么它们的最小公倍数 l c m ( a , b ) lcm(a, b) lcm(a,b) 可以表示为:

l c m ( a , b ) = a × b g c d ( a , b ) lcm(a, b) = \frac{a \times b}{gcd(a, b)} lcm(a,b)=gcd(a,b)a×b

因此,我们可以先用欧几里得算法计算出最大公约数,然后用上述公式计算最小公倍数。

需要注意的是,最小公倍数的值可能会很大,有可能超出 int 的范围。因此,我们需要使用 long long 类型来存储结果。

样例中包含了一些常见的情况:

  • 样例1是普通情况, l c m ( 3 , 5 ) = 15 lcm(3, 5) = 15 lcm(3,5)=15;
  • 样例2中一个数是另一个数的倍数, l c m ( 12 , 18 ) = 18 lcm(12, 18) = 18 lcm(12,18)=18;
  • 样例3中两个数是倍数关系, l c m ( 1024 , 2048 ) = 2048 lcm(1024, 2048) = 2048 lcm(1024,2048)=2048;
  • 样例4是两个大数的情况,结果已经超出了 int 的范围;
  • 样例5中考察 b = 1 b = 1 b=1 的特殊情况, l c m ( a , 1 ) = a lcm(a, 1) = a lcm(a,1)=a

通过这个问题,天秀可以深入理解最小公倍数的概念,并掌握求解最小公倍数的方法。同时,这个问题也提醒我们在计算过程中要注意数据范围,必要时使用更大的数据类型。
好的,我先给出题目的解题思路,然后再提供C++解答。

解题思路

  1. 最小公倍数的定义:两个或多个整数的公倍数中最小的一个。

  2. 最小公倍数与最大公约数的关系:设 a a a b b b 的最大公约数为 g c d ( a , b ) gcd(a, b) gcd(a,b),最小公倍数为 l c m ( a , b ) lcm(a, b) lcm(a,b),则有:

    l c m ( a , b ) = a × b g c d ( a , b ) lcm(a, b) = \frac{a \times b}{gcd(a, b)} lcm(a,b)=gcd(a,b)a×b

    这个关系表明,我们可以通过计算最大公约数来求得最小公倍数。

  3. 计算最大公约数可以使用欧几里得算法(辗转相除法):

    g c d ( a , b ) = g c d ( b , a m o d b ) gcd(a, b) = gcd(b, a \bmod b) gcd(a,b)=gcd(b,amodb)

    不断对 a a a b b b 进行取模运算,直到 b b b 0 0 0 为止,此时 a a a 就是最大公约数。

  4. 有了最大公约数,根据步骤2中的关系式,我们可以计算出最小公倍数。

  5. 注意,最小公倍数可能会很大,有可能超出 int 的范围。因此,我们需要使用 long long 类型来存储结果。

C++解答

#include <iostream>
using namespace std;typedef long long ll;ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);
}ll lcm(ll a, ll b) {return a / gcd(a, b) * b;
}int main() {ll a, b;cin >> a >> b;cout << lcm(a, b) << endl;return 0;
}

这个解答中:

  1. 我们定义了一个 long long 类型的别名 ll,以处理可能的大数据。

  2. gcd 函数使用了欧几里得算法的递归实现来计算最大公约数。

  3. lcm 函数根据最小公倍数和最大公约数的关系,通过最大公约数来计算最小公倍数。注意这里我们先进行除法运算,然后再进行乘法运算,以避免中间结果溢出。

  4. 在主函数中,我们读入 ab,调用 lcm 函数计算最小公倍数并输出结果。

这个解答的时间复杂度为 O ( log ⁡ ( min ⁡ ( a , b ) ) ) O(\log(\min(a, b))) O(log(min(a,b))),空间复杂度为 O ( 1 ) O(1) O(1)

希望这个详细的解题思路和C++解答对你有所帮助!如果你有任何其他问题,欢迎随时问我。
好的,我给你出一道结合最大公约数和最小公倍数知识点的应用题。

1.4.3 天秀的蛋糕分配问题

天秀有 n n n 个朋友,她想分给每个朋友一块蛋糕。她有两种蛋糕,一种是 a a a 克重的小蛋糕,另一种是 b b b 克重的大蛋糕。

天秀希望每个朋友分到的蛋糕重量都是一样的,且尽可能大。同时,为了不浪费,分给每个朋友的蛋糕重量必须是 a a a b b b 的整数倍。

请你帮天秀计算,每个朋友最多能分到多少克的蛋糕。

输入格式

第一行输入三个正整数 n n n, a a a, b b b,分别表示朋友的数量,小蛋糕的重量和大蛋糕的重量。

输出格式

输出一个整数,表示每个朋友最多能分到的蛋糕重量。

样例输入1

3 2 6

样例输出1

6

样例输入2

5 3 7

样例输出2

21

样例输入3

10 4 6

样例输出3

12

数据范围

  • 对于 30 % 30\% 30% 的数据, 1 ≤ n , a , b ≤ 1000 1 \leq n, a, b \leq 1000 1n,a,b1000;
  • 对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 9 1 \leq n \leq 10^9 1n109, 1 ≤ a , b ≤ 1 0 18 1 \leq a, b \leq 10^{18} 1a,b1018

题目解析

这道题看似是一个简单的分配问题,但实际上考察的是最小公倍数的应用。

  1. 每个朋友分到的蛋糕重量必须是 a a a b b b 的整数倍,因此每个朋友分到的蛋糕重量实际上是 a a a b b b 的公倍数。

  2. 为了让每个朋友分到尽可能大的蛋糕,我们应该选择 a a a b b b 的最小公倍数作为每个朋友分到的蛋糕重量。

  3. 最小公倍数可以通过最大公约数来计算:

    l c m ( a , b ) = a × b g c d ( a , b ) lcm(a, b) = \frac{a \times b}{gcd(a, b)} lcm(a,b)=gcd(a,b)a×b

  4. 因此,我们首先用欧几里得算法计算出 a a a b b b 的最大公约数,然后用上述公式计算出最小公倍数即可。

  5. 需要注意的是,最小公倍数可能会很大,有可能超出 int 的范围。因此,我们需要使用 long long 类型来存储结果。
    好的,下面是这个问题的C++解答:

#include <iostream>
using namespace std;typedef long long ll;ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);
}ll lcm(ll a, ll b) {return a / gcd(a, b) * b;
}int main() {ll n, a, b;cin >> n >> a >> b;cout << lcm(a, b) << endl;return 0;
}

解释:

  1. 我们定义了 long long 类型的别名 ll,以处理可能的大数据。

  2. gcd 函数使用欧几里得算法的递归实现来计算最大公约数。

  3. lcm 函数根据最小公倍数和最大公约数的关系,通过最大公约数来计算最小公倍数。注意这里我们先进行除法运算,然后再进行乘法运算,以避免中间结果溢出。

  4. 在主函数中,我们读入 n, ab。但实际上,我们并不需要使用 n 的值,因为每个朋友分到的蛋糕重量只取决于 ab 的最小公倍数。

  5. 我们调用 lcm 函数计算 ab 的最小公倍数,并输出结果。

这个解答的时间复杂度为 O ( log ⁡ ( min ⁡ ( a , b ) ) ) O(\log(\min(a, b))) O(log(min(a,b))),空间复杂度为 O ( 1 ) O(1) O(1)

需要注意的是,虽然题目中给出了 n 的范围,但实际上我们并不需要使用 n 的值。这是因为无论有多少个朋友,每个朋友分到的蛋糕重量都是一样的,都是 ab 的最小公倍数。

这个问题很好地展示了最小公倍数在实际应用中的作用。通过计算最小公倍数,我们可以解决许多看似复杂的问题。
好的,下面我再给你出一道应用最大公约数和最小公倍数知识点的题目,并提供5个经典的样例数据。

1.4.4 天秀的时钟问题

天秀有两个时钟,一个时钟每 a a a 分钟走一格,另一个时钟每 b b b 分钟走一格。现在两个时钟同时从12点开始走,请问经过多少分钟后,两个时钟会再次同时指向12点?

输入格式

输入两个正整数 a a a b b b,分别表示两个时钟走一格的分钟数。

输出格式

输出一个整数,表示两个时钟再次同时指向12点所需的分钟数。

样例输入1

2 3

样例输出1

6

样例输入2

5 7

样例输出2

35

样例输入3

12 18

样例输出3

36

样例输入4

1000000007 1000000009

样例输出4

1000000007000000009

样例输入5

123456789 987654321

样例输出5

121932631112635269

数据范围

  • 对于 30 % 30\% 30% 的数据, 1 ≤ a , b ≤ 1000 1 \leq a, b \leq 1000 1a,b1000;
  • 对于 60 % 60\% 60% 的数据, 1 ≤ a , b ≤ 1 0 6 1 \leq a, b \leq 10^6 1a,b106;
  • 对于 100 % 100\% 100% 的数据, 1 ≤ a , b ≤ 1 0 18 1 \leq a, b \leq 10^{18} 1a,b1018

题目解析

这道题看起来是一个时钟问题,但实际上是一个最小公倍数的应用。

  1. 两个时钟再次同时指向12点,实际上就是两个时钟走过的格数的最小公倍数。

  2. 设第一个时钟走 x x x 格,第二个时钟走 y y y 格,则有:

    a × x = b × y a \times x = b \times y a×x=b×y

    这实际上就是求 a a a b b b 的最小公倍数。

  3. 我们知道,最小公倍数可以通过最大公约数来计算:

    l c m ( a , b ) = a × b g c d ( a , b ) lcm(a, b) = \frac{a \times b}{gcd(a, b)} lcm(a,b)=gcd(a,b)a×b

  4. 因此,我们首先用欧几里得算法计算出 a a a b b b 的最大公约数,然后用上述公式计算出最小公倍数即可。

  5. 最小公倍数就是两个时钟再次同时指向12点所需的分钟数。

  6. 需要注意的是,最小公倍数可能会非常大,有可能超出 long long 的范围(例如样例4)。但在本题中,我们只需要输出结果,不需要对结果进行其他操作,所以不用担心溢出问题。

这个问题展示了最小公倍数在解决实际问题中的另一个应用。通过抽象问题,我们可以将问题转化为最小公倍数的计算。

好的,下面是这个问题的C++解答:

#include <iostream>
using namespace std;typedef long long ll;ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);
}ll lcm(ll a, ll b) {return a / gcd(a, b) * b;
}int main() {ll a, b;cin >> a >> b;cout << lcm(a, b) << endl;return 0;
}

解释:

  1. 我们定义了 long long 类型的别名 ll,以处理可能的大数据。

  2. gcd 函数使用欧几里得算法的递归实现来计算最大公约数。

  3. lcm 函数根据最小公倍数和最大公约数的关系,通过最大公约数来计算最小公倍数。注意这里我们先进行除法运算,然后再进行乘法运算,以避免中间结果溢出。

  4. 在主函数中,我们读入 ab,表示两个时钟走一格的分钟数。

  5. 我们调用 lcm 函数计算 ab 的最小公倍数,并输出结果。这个结果就是两个时钟再次同时指向12点所需的分钟数。

这个解答的时间复杂度为 O ( log ⁡ ( min ⁡ ( a , b ) ) ) O(\log(\min(a, b))) O(log(min(a,b))),空间复杂度为 O ( 1 ) O(1) O(1)

需要特别注意的是样例4,在这个样例中,ab 都是非常大的质数,它们的最小公倍数就是它们的乘积,这个结果已经超出了 long long 的范围。但在本题中,我们只需要输出结果,不需要对结果进行其他操作,所以不用担心溢出问题。在实际应用中,如果需要对这样的大数进行其他操作,就需要使用高精度计算了。

这个问题展示了如何将实际问题抽象为数学问题,并运用最大公约数和最小公倍数的知识来解决问题。这种思维方式在解决许多实际问题时都非常有用。

2. 质因数分解

2.1 质因数分解的定义

2.2 质因数分解的方法

2.2.1 试除法
2.2.2 埃拉托斯特尼筛法
2.2.3 欧拉筛法

2.3 质因数分解的应用

2.3.1 求最大公约数和最小公倍数
2.3.2 求因数的个数
2.3.3 判断一个数是否为质数

3. 最小质因数

3.1 最小质因数的定义

3.2 求最小质因数的方法

3.2.1 暴力枚举
3.2.2 预处理求最小质因数数组

3.3 最小质因数的应用

3.3.1 质因数分解
3.3.2 求因数的个数
3.3.3 欧拉函数的计算

4. 最大质因数

4.1 最大质因数的定义

4.2 求最大质因数的方法

4.2.1 质因数分解
4.2.2 试除法
4.2.3 预处理求最大质因数

4.3 最大质因数的应用

4.3.1 判断一个数是否为质数的幂
4.3.2 求一个数的因数个数
4.3.3 求一个数的所有因数

5. 相关问题

5.1 求一个数的所有质因数

5.2 求一个数的质因数的个数

5.3 求一个数的所有因数

5.4 求一个数的因数的和

5.5 求多个数的最大公约数和最小公倍数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/795007.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式总结-原型设计模式

原型设计模式 模式动机模式定义模式结构模式分析深拷贝和浅拷贝原型模式实例与解析实例一&#xff1a;邮件复制&#xff08;浅克隆&#xff09;实例二&#xff1a;邮件复制&#xff08;深克隆&#xff09; 模式动机 在面向对象系统中&#xff0c;使用原型模式来复制一个对象自…

MySQL 50 道查询题汇总,足以巩固大部分查询(附带数据准备SQL、题型分析、演示、50道题的完整SQL)

目录 MySQL 50 道查询题&#xff0c;足以巩固大部分查询数据准备&#xff1a;创建表sql添加表数据sql 50道查询题目汇总01 - 05 题&#xff1a;1、查询 “01” 语文成绩比 “02” 数学成绩高的学生的信息及课程分数2、查询 "01语文课程"比"02数学课程"成绩…

Linux云计算之网络基础9——园区网络架构项目

要求构建大型园区网络架构&#xff0c;方案如下&#xff1a; 园区A 园区c 公司B 要求&#xff1a; 1、A公司园区网络 一台汇聚层三层交换机&#xff0c;两台接入层二层交换机。 出口有一台路由器。 2、A园区有五台服务器。 分别为两台 WEB 服务器&#xff0c;…

java数据结构与算法刷题-----LeetCode405. 数字转换为十六进制数

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 分组位运算 分组位运算 这道题正常来说可以用转换7进制的思想来&…

PTA C 1050 螺旋矩阵(思路与优化)

本题要求将给定的 N 个正整数按非递增的顺序&#xff0c;填入“螺旋矩阵”。所谓“螺旋矩阵”&#xff0c;是指从左上角第 1 个格子开始&#xff0c;按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列&#xff0c;满足条件&#xff1a;mn 等于 N&#xff1b;m≥n&#xff1b;且…

【蓝桥杯-读数据】

蓝桥杯-读数据 P8598 [蓝桥杯 2013 省 AB] 错误票据 P8598 [蓝桥杯 2013 省 AB] 错误票据 这道题本身很简单&#xff0c;最大的难点在于读入数据。 #include<bits/stdc.h> using namespace std; #define int long long const int N 2e5 10; int a[N]; signed main()…

人工智能技术的未来创业风口:洞察趋势,把握机遇

人工智能技术的未来创业风口&#xff1a;洞察趋势&#xff0c;把握机遇 引言 在科技的洪流中&#xff0c;人工智能&#xff08;AI&#xff09;如同一颗璀璨的明珠&#xff0c;以其强大的潜力颠覆着各行各业的传统运作模式&#xff0c;并为全球创业者开辟了无数崭新的商业蓝海。…

探寻马来西亚服务器托管的优势与魅力

随着全球跨境业务的不断增加&#xff0c;境外服务器成为越来越受欢迎的选择。在这其中&#xff0c;马来西亚服务器备受关注&#xff0c;其机房通常位于马来西亚首都吉隆坡。对于客户群体主要分布在东南亚、澳大利亚和新西兰等地区的用户来说&#xff0c;马来西亚服务器是一个理…

SV学习笔记(七)

类型转换 写在前面 类型转换可以分为 静态转换和动态转换 。静态转换即需要在转换的表达式前 加上单引号 即可&#xff0c;该方式并不会对转换值做检查。如果发生转换失败&#xff0c;我们也无从得知。动态转换即需要使用 系统函数$cast(tgt&#xff0c; src) 做转换。静态转…

【算法】初识算法

尽量不说废话 算法 一、数据结构二、排序算法三、检索算法四、字符算类型算法五、递归算法六、贪心算法七、动态规划八、归一化算法后记 我们这里指的算法&#xff0c;是作为程序员在计算机编程时运用到的算法。 算法是一个庞大的体系&#xff0c;主要包括以下内容&#xff1a;…

ViT模型实现-模型准备。偏置项。缩放因子。qkv(x)输入,输出。嵌入向量是什么

目录 ViT模型实现-模型准备。 偏置项。 偏置项是什么举例。 缩放因子

一点点安全资料:漏洞利用知识扩展

协议扩展 加密协议SSL/TLS 简介 SSL&#xff08;Secure Sockets Layer&#xff09;和TLS&#xff08;Transport Layer Security&#xff09;是加密协议&#xff0c;设计用来提供网络通信的安全性和数据完整性。尽管TLS是SSL的后继者&#xff0c;但两者的核心目标相同&#x…

CountDownLatch 详解

CountDownLatch 用法详解 CountDownLatch 详解1 原理2 常见用法3 方法介绍4 示例及使用 CountDownLatch 详解 CountDownLatch&#xff08;倒计时门闩&#xff09;是Java并发包中的一个工具类&#xff0c;用于协调多个线程之间的同步。它允许一个或多个线程等待其他线程完成操作…

常见的DOM元素与JavaScript的交互方式[示例]

DOM&#xff08;Document Object Model&#xff09;是一个编程接口&#xff0c;用于在浏览器中表示和操作 HTML 和 XML 文档。通过 DOM&#xff0c;开发人员可以使用 JavaScript 等编程语言来操纵网页上的各种元素&#xff0c;例如添加、删除、修改元素、响应用户事件等。 以下…

【软件工程】测试规格

1. 引言 1.1简介 本次的测试用例是基于核心代码基本开发完毕&#xff0c;在第一代系统基本正常运行后编写的&#xff0c;主要目的是为了后续开发与维护的便利性。 该文档主要受众为该系统后续开发人员&#xff0c;并且在阅读此文档前最后先阅读本系统的需求文档、概要设计文…

谷歌推出多模态视频模型,自动生成丰富动作视频

谷歌的研究人员推出了一款多模态扩散模型——VLOGGER。 用户只需要向VLOGGER输入图像、语音&#xff0c;就能生成带语音、丰富动作的人物视频。VLOGGER基于扩散模型开发而成&#xff0c;并提出了一种全新的架构&#xff0c;将文本生成图像模型与空间、时间控制相结合&#xff…

使用Python转换图片中的颜色

说明&#xff1a;最近在看梵高的画册&#xff0c;我手上的这本画册&#xff08;《文森特梵高》杨建飞 主编&#xff09;书中说&#xff0c;梵高用的颜料里有不耐久的合成颜料&#xff0c;原本的紫色褪成了我们现在所看到的灰蓝色。于是我想&#xff0c;能不能用程序将画中的颜色…

【Rust】基础语法

变量&#xff0c;基本类型&#xff0c;函数&#xff0c;注释和控制流&#xff0c;这些几乎是每种编程语言都具有的编程概念。 这些基础概念将存在于每个 Rust 程序中&#xff0c;及早学习它们将使你以最快的速度学习 Rust 的使用。 变量 首先必须说明&#xff0c;Rust 是强类…

单链表的排序

目录 题目来源&#xff1a; 题目描述&#xff1a; 初始代码&#xff1a; 思路&#xff1a; 具体做法&#xff1a; 我的代码&#xff1a; 优化代码&#xff1a; 对比&#xff1a; 复习&#xff1a;List 基本介绍 常用方法 遍历方式 题目来源&#xff1a; 单链表的排…

MySQL常见锁探究

MySQL常见锁探究 1. 各种锁类型1.1 全局锁1.2 表级锁1.2.1 表锁1.2.2 元数据锁&#xff08;MDL&#xff09;1.2.3 意向锁1.2.4 AUTO-INC 锁 1.3 行级锁1.3.1 Record Lock1.3.2 Gap Lock1.3.3 Next-Key Lock 2. MySQL是如何加锁的&#xff1f;2.1 什么 SQL 语句会加行级锁&#…