HDOJ1019解题报告
Least Common Multiple
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 13970 Accepted Submission(s): 5194
Problem Description
The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set. For example, the LCM of 5, 7 and 15 is 105.
Input
Input will consist of multiple problem instances. The first line of the input will contain a single integer indicating the number of problem instances. Each instance will consist of a single line of the form m n1 n2 n3 ... nm where m is the number of integers in the set and n1 ... nm are the integers. All integers will be positive and lie within the range of a 32-bit integer.
Output
For each problem instance, output a single line containing the corresponding LCM. All results will lie in the range of a 32-bit integer.
Sample Input
2 3 5 7 15 6 4 10296 936 1287 792 1
Sample Output
105 10296
题目主要是要求最小公倍数,刚开始想到的是通过寻找每个数的质数分解,将不重复的存入一个数组,然后一一相乘会得到正确的结果,5*7*3=105,但到第二个例子就不对,解出来竟然比10296还小。那干脆,就取这个“最大公约数”和原数列中最大的一个中比较大的一个作为结果吧。
然后还是一直WA,参考了别人的程序。
4 23 89 12 34
别人的输出417588
我的输出208794
刚好相差了2倍,会不会因为12和4都能被4整除还得把4也作为公约数?
说干就干:思路就是把最小质数2换成(12,24的公约数4),然后答案就应该刚好了,这样的思路我想应该是先从2下手,然后一旦一个数,比如12 ,能被2整除,就测试它能不能被4整除。以此类推,测试所有的输入数。如果所有的数都满足(要么不能被2整除,要么能被4整除),那么我们就把2换成4。那要是还有8呢?,所以一直循环,
2*2*2。。。。,看以上条件满不满足,只要出现不满足,那就说明这个2^n不可行,那就取2^n-1 ,这就是解释最大的约数。
就这样办,这个答案还是有问题,34满足被2整除但不被4整除。。。反正也觉得这种思路有点二。。就放弃吧。。以下是删节后的代码(能求最小约数相乘的)。。。
#include<iostream> #include<iomanip> #include<string> #include<cmath> using namespace std; //bool isDigit(int a){ // for(int i=2;i<a;i++){ // if(a%i==0)return false; // } // return true; //} bool alreadyExist(int *s,int len,int zs){ for(int i=0;i<len;i++){ if(s[i]==zs)return true; } return false; } void main(){ int N; cin>>N; //这是每个例子的循环 for(int i=0;i<N;i++){ long LCM=1,max=0; int num,count; int tempzs[1000]; cin>>count; //循环录入和处理每个输入数 int k=0; for(int j=0;j<count;j++){ cin>>num; if(num>max)max=num; for(int x=2;x<=num;x++){ if(num%x==0){//可以除尽,是质数 if(!alreadyExist(tempzs,k,x))tempzs[k++] = x; num/=x; x=1; } } if(num>1 && !alreadyExist(tempzs,k,num))tempzs[k++] = num; } while(k-->0){ LCM*=tempzs[k]; } cout<<(LCM>max?LCM:max)<<endl; } }
这是其它人那儿的思路,先求两个数的最大公约数:
通过不断求y=x%y和x=y,直到x%y=0(可以除尽)为止。此时的y应该是原x和y的最大公约数,那么x和y的最小公倍数只应该是他们非公约数部分相乘在乘以一倍的最大公约数。即x*y/一倍的最大公约数。这个是他写在函数LCM中的核心代码。
其它,我觉得他采用了vector<long>泛型容器类来存储输入的数组,可以方便的传递多参数,方便进行遍历和管理。这点是我在以后编程过程当中应该借鉴的。
首先,新建一个对象 vector<long> numVect;
然后用push_back方法往其中插入数据numVect.push_back(tmp);
可以方便当参数传递哦doProcess(numVect);
函数的签名如此:void doProcess(vector<long>& v)
然后遍历求最小公倍数for (int i=2;i<v.size();++i) temp = LCM(temp,v[i]);
好。如下是源代码:
#include<iostream> #include <vector> using namespace std; int LCM(long x,long y) { long temp; long a,b; a=x; b=y; while(x%y!=0) { temp=x%y; x=y; y=temp; } return a/y*b; } void doProcess(vector<long>& v) { if (v.size()==1) {//只有一个数据 cout<<v[0]<<endl; return; } int temp = LCM(v[0],v[1]); for (int i=2;i<v.size();++i) { temp = LCM(temp,v[i]); } cout<<temp<<endl; } int main() { int caseNum,i,j,n,tmp; while (cin>>caseNum) { for (i=0;i<caseNum;++i) { cin>>n; vector<long> numVect; for (j=1;j<=n;++j) { cin>>tmp; numVect.push_back(tmp); } doProcess(numVect); } } return 0; }