题目链接:n个数的最小公倍数
【题目描述】
求n个数的最小公倍数
第一行一个数n(n<10)
下面n个数,integer范围内
【输出描述】
这n个数的最小公倍数
【样例输入】
5
6 3 5 4 2
【样例输出】
60
【数据范围及提示】
求出最大公约数后可用公式求最小公倍数
题目分析:
求解n个数的最小公倍数一般有两种做法:
1.分解质因数法:先把这几个数分解质因数,再把它们一切公有的质因数和其中几个数公有的质因数以及每个数的独有的质因数全部连乘起来,所得的积就是它们的最小公倍数.
12 15 8 9
12=2*2*3
15=3*5
8=2*2*2
9=3*3
其中12和8公有两个2,而12,15,9则公有质因子3,剩下的15独自有一个5,8独自有一个2,9独自有一个3
因此:最小公倍数为2*2*3*5*2*3=360
这种方法个人觉得适合人去算,并不适合计算机去计算。计算机更适合采用第二种方法。
2.公式法两两运用
假设现在要求最小公倍数的两个数为x,y,他们的最大公约数为p,最小公倍数为q。则x*y=p*q,也就是说只要求得两个数的最大公约数就可求得这两个数的最小公倍数。
但是题目中要求的是n个数的 最小公倍数,这里只需要用最小公倍数代替原来的两个数即可。
例如:12 15 8 9
第一步:求得12和15的最小公倍数为60
第二部:求得60和8的最小公倍数为120
第三步:求得120和9的最小公倍数为360
所以,原问题转换为求两个数的最大公约数。最大公约数有几种求法,第一种对于小整数的辗转相除,大整数用辗转相减,还有优化版本的辗转相减法,这里给定数字范围为int因此直接采用辗转相除法。
辗转相除求最大公约数O(lgn)
递归写法:
int gcd(int a,int b){
if(b==0)
return a;
else
return gcd(b,a%b);
}
非递归写法:
int gcd(int a,int b){
int c;
while(b){
c=a;
a=b;
b=c%b
}
return a;
}
利用x*y=q*p得到最小公倍数q=x*y/p;
完整代码 O(nlg(max{arr})):
#include<iostream>
using namespace std;
int arr[11];
int gcd(int a,int b){//两个方法任选一个
if(b==0)
return a;
else
return gcd(b,a%b);
}
int getGcd(int a,int b){
int c;
while(b){
c=a;
a=b;
b=c%b;
}
return a;
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i];
if(i!=1){
arr[i]=arr[i-1]/getGcd(arr[i-1],arr[i])*arr[i];
}
}
cout<<arr[n]<<endl;
}
存在问题:
1.如果直接使用x*y/p存在溢出的风险
2.使用x/p*y可一定程度上避免溢出,但是依然不能完全规避;例如x=2^31-1,y=2,因此这里建议采用long long int;当然oj中给出的测试数据并没有出现溢出的情况,使用上面的代码依然能够AC