n个数的最大公因数和最小公倍数

 

一.题目要求:求N个数的最大公约数和最小公倍数

二.题目背景

        anks博士是BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson正在思考一个有趣的问题。

今天在课堂上,老师讲解了如何求两个正整数c1和c2的最大公约数和最小公倍数。现在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数x满足:

1、  x和a0的最大公约数是a1;

2、  x和b0的最小公倍数是b1。

Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮助他编程求解这个问题。

输入格式

输入第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0能被a1整除,b1能被b0整除。

输出格式

输出共n行。每组输入数据的输出结果占一行,为一个整数。

对于每组数据:若不存在这样的x,请输出0;

若存在这样的x,请输出满足条件的x的个数;

样例输入

2

41 1 96 288

95 1 37 1776

样例输出

6

2

三.设计思路

      背景中所给的输入情况有两种,第一种输入的是组数,第二种输入的是要计算的数据,因为题目给出要输入的数据只有四个,a0,a1,b0,b1,而要输入的组数是个未知数,所以我的想法是定义两个未知大小的二维数组,一个负责计算,一个负责备份,分别保存组数和数据,我定义一个x在10000之内,再通过一个辗转相除法分别计算未知x与数据中两两组合的最大公因数和最小公倍数,输出存在x的个数。

四.整体代码


#include <iostream.h>
#include <math.h>
#include <conio.h>
#include <stdlib.h>
void jisuan(int **a,int **b)
{
	int i,x,n,t,y,z;
	cout<<"请再次输入组数:";
	cin>>n;

	for(i=0;i<n;i++)
	{
		int c,d,e,f,m=0;
		c=a[i][0];
		e=a[i][2];
		d=b[i][0];
		f=b[i][2];

		if(a[i][0]%a[i][1]!=0)
		{
			cout<<"输入的数字有误"<<endl;
			break;
		}

		if(a[i][3]%a[i][2]!=0)
		{
			cout<<"输入的数字有误"<<endl;
			break;
		}

		for(x=1;x<10000;x++)                  
		{
			z=x;
			y=x;

		    if(z<c)                     //求最大公因数
			{
	    	    t=z;
				z=c;
				c=t;              
			}
    	    while(c!=0)                   
			{
	     	    t=z%c;                
	    	    z=c;                    
		        c=t;
			}
			int w;                     //求最小公倍数
			w=y*e;
		    if(y<e)                     
			{
	    	    t=y;
				y=e;
				e=t;              
			}
    	    while(e!=0)                   
			{
	     	    t=y%e;                
	    	    y=e;                    
		        e=t;
			}
	        if(w/y==a[i][3] && z==a[i][1])
			{
			    m++;
			}
			c=d;
			e=f;
		}
		cout<<"满足第"<<i+1<<"组的个数:";
		cout<<m<<endl;
	}
}

void main()
{
	int n,i,j;
	int **a,**b;                           //定义两个二维数组
	cout<<"请输入组数:";
	cin>>n;	
	a=new int*[n];
	b=new int*[n];
	for(i=0;i<n;i++)
	{
		a[i]=new int[4];
		b[i]=new int[4];
	}
	for(i=0;i<n;i++)
	{			
		cout<<"请输入第"<<i+1<<"组数"<<endl;
		for(j=0;j<4;j++)
		{
			cin>>a[i][j];                      //a用来计算,b用来保存
			b[i][j]=a[i][j];                    
		}
	}
	jisuan(a,b);
}

五.调试,测试。

六.总结

        刚开始浏览这道题的时候不知道该怎么下手,题目可以理解就是不知道用什么方法来完善代码,但还是通过定义一个二维数组解决了问题。

        开始时,最大的问题是不知道怎么定义一个未知大小的二维数组,因为后面的算法不是很难设计,最重要的是该如何来保存这些数字,通过网上的知识才学习到了。

定义未知大小二维数组的方法

cin>>m>>n;

int **a,i;

a=new int *[m];

for(i=0;i<m;i++)

{

a[i]=new int [n];

}

此时就可以完成定义一个未知大小的二维数组。

        后面在写算法时遇到的问题是一直陷入死循环,因为整段代码都在经历变量之间的数值相互转换,每转换一次都必须要将那个变量返回初值才可以进行下一个循环,所以我同时设定了多个变量,争取每个数据都保存在两个不同的变量中。

       现在还存在的问题是,我给定的x的范围是1~10000之间,也就是这个x是有范围的,如果输入的数字过大,那么可以输出x的个数可能就不是那么准确。

发布了16 篇原创文章 · 获赞 3 · 访问量 1107

猜你喜欢

转载自blog.csdn.net/qq_41890177/article/details/88759827