求N个数的最大公因数和最小公倍数问题+hanks son问题

求N个数的最大公因数和最小公倍数问题

想法思路

基本要求的解决:(1)写出求两个数的最大公约数
(2)写出求两个数的最小公倍数
(3)利用循环和递归求N个数的最大公约数和最小公倍数
1.求两个数的最大公约数实现流程图:
在这里插入图片描述
2.求两个数的最小公倍数实现流程图:
在这里插入图片描述
3.利用循环和递归求N个数的最大公约数和最小公倍数实现流程图如图 2-3 所示:
在这里插入图片描述

代码片段

int min,max;
void gcd(int a,int b)     //最大公约数 
{
	int temp;
	if(a<b)               //总使得a>b
	{
		temp=a;
		a=b;
		b=temp;
	}
	while(b!=0)
	{
		temp=a%b;
		a=b;
		b=temp;
	}
	max=a;
}

void lcm(int c,int d)     //最小公倍数
{
     min=c*d/max; 
} 

int main()
{
	int x[100];
	int n;
	cout<<"请输入你将要查询的数目个数"<<endl;
	while(cin>>n)
	{
		for(int i=0;i<=n-1;i++)
		{
			cin>>x[i];
		}
	    gcd(x[0],x[1]);
		lcm(x[0],x[1]);
		if(n>2)
		{
			for(i=2;i<=n-1;i++)
			{
				gcd(max,x[i]);
				lcm(min,x[i]);
			}
		}
	  cout<<"这些数字的最大公约数为:"<<max<<endl;
	  cout<<"这些数字的最小公倍数为:"<<min<<endl;	
	}
}

测试调试与测试截图

(1)调试步骤
1.在函数gcd,函数lcm,主函数前F9加入断点。
在这里插入图片描述
2.F5启动调试,调试数据(以三个数字,2,4,5为例)
F10单步调试,最后一个数字循环输入完成
在这里插入图片描述
3.输入完成后,可以看到i=2,x[i]=5。
在这里插入图片描述
4.x[0]=2,x[1]=4。
在这里插入图片描述
5. 2小于4,进行数据交换
在这里插入图片描述
在这里插入图片描述
6.执行完temp=a%b。可以看到结果temp=0。
在这里插入图片描述
7.执行a=b;
在这里插入图片描述
8.执行b=temp 。
在这里插入图片描述
9.此时光标移到while循环,判断b是否为0。
在这里插入图片描述
10.判断不为0后,光标移至max=a处。
在这里插入图片描述
在这里插入图片描述
11.开始求x[0],x[1]的最小公倍数。
在这里插入图片描述
12.得到c=x[0]=2,d=x[1]=4,max=2。
在这里插入图片描述
13.计算得到min=4。
在这里插入图片描述
14.进行n的判断,如果数组超过两个数,将从第三个数开始进行循环。
在这里插入图片描述
15.同之前的步骤,第三个数循环完成,2,4,5得到结果max=1,min=20。
在这里插入图片描述
16.调试结束,按Shift+F5退出调试界面。

(2)测试
1.数组中含有0。
在这里插入图片描述
2.数组中含有1。
在这里插入图片描述
3.数组中含有重复数字。
在这里插入图片描述
4.多数据测试
在这里插入图片描述

感悟

刚开始的想法是写递归函数,gcd(x[i],x[i+1],i),通过i的不同来使得数组的元素进行求最大公约数和最小公倍数运算。但是数组不能做形参,形参不能被分配空间,只能做实参。然后就想着先写出两个数的运算,之后再对数组进行循环调用函数。

在调试的过程中,发现了在求最小公倍数的时候,最小公倍数中嵌套了最大公约数的函数,导致最大公约数又执行了一遍,因为之前max已经求出来,不必要再进行这个操作,所以对此进行了优化,删去了gcd(c,d);语句。

优化前:
在这里插入图片描述
优化后:
在这里插入图片描述

hanks son问题

问题描述:“逆问题”,已知正整数a0,a1,b0,b1,求某未知正整数x满足:
1.x和a0的最大公约数为a1
2.x和b0的最小公倍数为b1
(x并不唯一,也有可能不存在)

代码片段:

void gcd(int a,int b)     //最大公约数 
{
	int temp;
	if(a<b)               //总使得a>b
	{
		temp=a;
		a=b;
		b=temp;
	}
	while(b!=0)
	{
		temp=a%b;
		a=b;
		b=temp;
	}
	max=a;
}
void lcm(int c,int d)     //最小公倍数
{
	gcd(c,d);            //数据改变,max随之改变,基础程序删掉的得加上
     min=c*d/max; 
	 gcd(x,a0);         //归原max
} 
int main()
{
	int ans=0;          //计数器
	int n,a;
	cout<<"请输入您将使用的数据组数"<<endl;
    cin>>n;
    while(n--)
	{
	   cout<<"请输入a0,a1,b0,b1"<<endl;
	   cin>>a0>>a1>>b0>>b1;
 	   for(x=0;x<=x*b0;x++)
	   {
	      gcd(x,a0);
	      lcm(x,b0);
		  if((a1==max)&&(b1==min))
		  {
	          //	cout<<x<<endl;     可查看x的值
			  ans++;
		  }
	   }
	  cout<<"满足要求的x个数为:"<<ans<<endl;
	  ans=0;        //使ans回归为0,以便后面的数据组进行计数
	  }
}

解决过程

先进行一组样例输入程序的编写,编写后程序没有错误,但是结果与样例不同。通过单步调试(基础程序已详细展示调试过程,此处不进行展示),发现了两个问题:
在这里插入图片描述
解决方案实现程序:
在这里插入图片描述
利用循环进行多组输入,运算,此时的问题:计数器ans在进行完第一组数据的时候并未归0,所以第二组数据输出的ans是加上了第一组的ans。
例:输入样例:
在这里插入图片描述
本来第二组的x个数应该为2,此时为8,出现错误。
解决:在循环的最后加上ans=0;使计数器归0。
在这里插入图片描述
提高程序完成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值