求一组数的最大公约数和最小公倍数

求一组数的最大公约数和最小公倍数

问题描述
1.【简单练习】求N个数的最大公约数和最小公倍数
2.【提高练习】Hanks博士是BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson正在思考一个有趣的问题。今天在课堂上,老师讲解了如何求两个正整数c1和c2的最大公约数和最小公倍数。现在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数x满足:
①x和a0的最大公约数是a1;
②x和b0的最小公倍数是b1。
Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮助他编程求解这个问题。
输入格式 : 输入第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0能被a1整除,b1能被b0整除。
输出格式输出共n行。每组输入数据的输出结果占一行,为一个整数。对于每组数据:若不存在这样的x,请输出0;若存在这样的x,请输出满足条件的x的个数;
样例输入:

41 1 96 288
95 1 37 1776

样例输出:

6
2

解题思路
①求一组数最大公约数和最小公倍数
用gcd()函数求出前两个数的最大公约数,用这两个数求得的这个最大公约数和后一位数求最大公约数,以此类推,最后求得一组数的最大公约数。最小公倍数可以用两个数相乘除以最大公约数来计算,这里就要用到上边的gcd()函数,通过循环,来求一组数的最小公倍数和最大公约数一样的道理。
②Hankson问题
通过阅读题目就可以得到两个简单的函数gcd(x,a0)=a1(x和a0的最大公约数为a1);lcm(x,b0)=b1;(x和b0的最小公倍数为b1)
然后通过最小公倍数可以用两个数相乘除以最大公约数来计算这个方法,来变换这两个函数,最后得到gcd(x/a1,a0/a1)==1;gcd(b1/b0,b1/x)==1;(gcd()函数作用是用辗转相除法求两个数的最大公约数)这两个式子,这两个式子就是求x的条件语句,x满足两个函数则累加,最后求得x的个数。
源代码
求一组数的最大公约数和最小公倍数源代码

#include<iostream>
using namespace std;
//辗转相除法
int gcd(int a,int b)
{
    int temp;
 if(a<b)         //用a来存大数
 {
  temp=a;
  a=b;
  b=temp;
 }
 while(b!=0)
 {
  temp=a%b;
  a=b;
  b=temp;
 }
 return a;
}
int main()
{
    int row,col,i;
    cout<<"输入数的个数:";
//用动态一维数组来存放数字
    cin>>row ;
     int *a ;
    a=new int [row] ;
//输入一维数组的值
 cout<<"输入数字:";
     for(i=0;i<row;i++)
     cin>>a[i];
  int maxfac,minmul;//定义最大公约数和最小公倍数
  maxfac=gcd(a[0],a[1]);
     minmul=(a[0]*a[1])/gcd(a[0],a[1]); //最小公倍数也可以用它们相乘除以最大公约数来计算
  for(i=0;i<row;i++)
  {
   maxfac=gcd(maxfac,a[i]);//调用函数求一组数的最大公约数
         minmul=((minmul*a[i])/gcd(minmul,a[i])); 
  }
  cout<<"最大公约数为:"<<maxfac<<endl;
  cout<<"最小公倍数:"<<minmul<<endl;
//释放一维数组
delete [] a ;
}

求Hankson问题源代码

#include<iostream>
using namespace std;
int gcd(int a,int b)//辗转相除法求最大公约数
{
 int temp;
 if(a<b)      //用a存较大的数
 {
  temp=a;
  a=b;
  b=temp;
 }
 while(b!=0)
 {
  temp=a%b;
  a=b;
  b=temp;
 }
 return a;
}
int main()
{
 int n,a0,a1,b0,b1,x,ans;
    cout<<"请输入组数:";
 cin>>n;
 if(n<0)
 {
  cout<<"输入数据错误,请输入正整数"<<endl;
 } 
 while(n>0)
 {
  ans=0;
  cout<<"请依次输入a0,a1,b0,b1(保证a0能被a1整除,b1能被b0整除):"<<endl;
  cin>>a0>>a1>>b0>>b1;
  for(int i=1;i<=b1;i++)//找符合条件的x
   if(b1%i==0)
   {
    x=i;
    if(x%a1==0)
     if(gcd(a0/a1,x/a1)==1&&gcd(b1/b0,b1/x)==1)//x满足的条件
      ans++;
   }
   cout<<"满足条件的个数有"<<ans<<"个"<<endl;
   n--;//退出while循环
 }
}

经验总结
这次作业练习学到了一种新的求最小公倍数的思维方法(用两个数相乘除以最大公约数来计算),在要同时求最大公约数和最小公倍数时,这种方法更加简便。很好的锻炼了思维能力,之前看见编程的题目一头雾水,不知道从哪开始思考分析,现在练习了能多编程的题目,实际操作,学到很多东西,也慢慢学会了怎样分析问题,用什么样的方法,还有解决问题的思路,要逻辑分明,条理清晰。比如说Hankson的问题,读完题目就可以写出两个函数gcd(x,a0)=a1;lcm(x,b0)=b1;根据这两个式子和上边求最小公倍数的方法得到另外两个推导式gcd(x/a1,a0/a1)==1;gcd(b1/b0,b1/x)==1;就出现了求x的两个条件,这个推导也是参考了很多网上的例子,知道了方法编程也就变容易了点。自己的思维逻辑能力还是有点差,还是要多实践,多编一些程序,锻炼锻炼逻辑能力。

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值