题目:求n个数的最小公倍数。
对于这个简单的关于数论的题目时,首先需要学会的是求两个数的最大公约数
求最大公约数的方法有辗转相除法,更像减损术
辗转相除法(循环)得到两个数,将小数除大数,如果得到的余数不为0,则将
除数付给被除数,余数赋给除数,再相除求余,判断余数是否为0。
int a, b;
while(scanf("%d %d", &a, &b) != EOF) {
int max_ = max(a, b);
int min_ = min(a, b);
int mo = max_ % min_;
while(mo != 0) {
max_ = min_;
min_ = mo;
mo = max_ % min_;
}
printf("%d\n", min_);
}
递归:
int Max_Divisor(int max_, int min_) {
int mo = max_ % min_;
if(mo == 0) {
return min_;
}
max_ = min_;
min_ = mo;
return Max_Divisor(max_, min_);
}
int a, b;
while(scanf("%d %d", &a, &b) != EOF) {
int max_ = max(a, b);
int min_ = min(a, b);
printf("%d\n", Max_Divisor(max_, min_));
}
- 更相减损术
得到两个数,如果两个数同时为偶数,将这两个数都除以2,直到有一个数不为偶数,记录下一共除了几次2,然后用这两个数,大数减小数,如果得到的差和减数相等,就停止,输出用差乘上乘上2 ……次数,如果不等,将差和减数比较,大的减小的,再判断。
int a, b;
while(scanf("%d %d", &a, &b) != EOF) {
int max_ = max(a, b);
int min_ = min(a, b);
int c;
int Count = 1;
while(1) {
if(min_ % 2 == 0 && max_ % 2 == 0) {
min_ /= 2;
max_ /= 2;
Count *= 2;
cout << Count << endl;
continue;
}
c = max_ - min_;
max_ = max(c, min_);
min_ = min(c, min_);
//cout << max_ << min_ << endl;
if(c == min_) {
break;
}
}
printf("%d\n", c * Count);
求n个数的最大公倍数,两个数的最小公倍数 = 乘积 / 最大公约数
有(a1, a2, a3,…an), 先求(a1,a2)的最小公倍数,设为ai,再求(ai, a3)的最小公倍数,以此类推,需要n - 1次循环
然后有一个错误的思考:既然公倍数可以这样求,那公约数也可以,然后就求n个数的最大公约数,然后再得到n个数的乘积,再将他们相除,答案是错误的。
所以应该一个一个的求。
//#define LOCAL
#include <iostream>
#include <algorithm>
#include <cstdio>
using std::cout; using std::cin; using std::endl; using std::max; using std::min;
int Get(unsigned int a, unsigned int b) {
unsigned int mul = a * b;
unsigned int max_ = max(a, b);
unsigned int min_ = min(a, b);
unsigned int mo = max_ % min_;
while(mo != 0) {
max_ = min_;
min_ = mo;
mo = max_ % min_;
}
return mul / min_;
}
int main() {
int n;
while(scanf("%d", &n) != EOF) {
unsigned int m[10000];
for(int i = 0; i < n; i++) {
scanf("%u", &m[i]);
}
for(int i = 0; i < n; i++) {
if(i + 1 == n) break;
m[i + 1] = Get(m[i], m[i + 1]);
}
printf("%u\n", m[n - 1]);
}
}