博客
关于我
N个数的最大公约数和最小公倍数及Hankson的趣味题
阅读量:337 次
发布时间:2019-03-04

本文共 5815 字,大约阅读时间需要 19 分钟。

N个数的最大公约数和最小公倍数。

题目内容及要求:

1.求N个数的最大公约数和最小公倍数。
2.提高要求:
题目描述
已知正整数a0,a1,b0,b1。设某未知正整数x 满足:
1. x 和a0 的最大公约数是a1;
2. x 和 b0 的最小公倍数是 b1。
求解满足条件的 x 的个数
输入
第一行为一个正整数n,表示有n 组输入数据。接下来的n 行每行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0 能被a1 整除,b1 能被b0 整除。
[说明]:
第一组输入数据,x 可以是9、18、36、72、144、288,共有6 个。
第二组输入数据,x 可以是 48、1776,共有 2 个。
[数据规模]:
对于 50%的数据,保证有1≤a0,a1,b0,b1≤10000 且n≤100。
对于 100%的数据,保证有 1≤a0,a1,b0,b1≤2,000,000,000 且 n≤2000。
输出
若不存在这样的x,请输出0;
若存在这样的x,请输出满足条件的x的个数。
样例输出
2
41 1 96 288
95 1 37 1776

算法设计

1.对于求N个数的最大公因数和最小公倍数。
1)对于最大公因数,用辗转相除法求最大公约数。可以使用递归和迭代两种写法。
2)对于最小公倍数,两个数的乘积等于这两个数的最大公因数和最小公倍数的乘积。
2.对于提高要求中的Hanson“逆问题”的解决。首先由最大公因数和最小公倍数的性质可知,令p = a0/a1,q = b1/b0,它们与x的公因数为1,并且x也是b1(最小公倍数)的一个因子。所以令x从1到sqrt(b1)中是b1(最小公倍数)的一个因子,除此之外还有b1/x,也可能是其中的一个因子,用以上条件进行判定。

求两个数的最大公约数:

int GCD(int m,int n){   	//递归写法 	if(n == 0)	{   		return m;	}	return GCD(n,m%n);	/*	//迭代写法            while(n != 0){            int t = n;            n= m % n;            m = t;        }        return m;    }	*/}

求两个数的最小公倍数:

int LCM(int m,int n){   	return (m*n)/GCD(m,n);}

判断输入数据的正确性

int inspect(int *array,int number){   	for(int i = 0;i<number;i++){   		if(array[i] == 0 || (int)array[i] != array[i])		{   			system("cls"); 			cout<<"输入数据中包含0或者非法字符,请重新输入"<<number<<"个数字:"<<endl;			cin.clear();                          //恢复cin状态             cin.sync();   //清除缓冲区的数据流 			return 0; 		}	}	return 1;}

Hankson的相关算法

int Hanson(int line_number){   	int number = 0;	int count[line_number];	while(line_number--) 	{           int a0,a1,b0,b1;                //对输入数据进行判断         while(1)        {           	cin>>a0>>a1>>b0>>b1;        	if(a0%a1 != 0 || b1%b0 != 0)        	{           		cout<<"输入数据有误,请重新输入这组数据!"<<endl;        		continue;			}			else{   				break;			}		}                int p=a0/a1,q=b1/b0,ans=0;        for(int x=1;x*x<=b1;x++)             if(b1%x==0)			{     //x是b1的一个因子                 if(x%a1==0&&GCD(x/a1,p)==1&&GCD(q,b1/x)==1) ans++;                int y=b1/x;      //y是另一个因子                 if(x==y) continue;                 if(y%a1==0&&GCD(y/a1,p)==1&&GCD(q,b1/y)==1) ans++;            }            count[number] = ans;            number++;    }    for(int i = 0;i<number;i++)    {       	cout<<count[i]<<endl;	}}

相关运行结果截图

对N个数进行最大公约数和最小公倍数运行结果截图
Hankon运行结果截图

全部代码

//辗转相除法, 又名欧几里得算法(Euclidean algorithm),目的是求出两个正整数的最大公约数 /***实现功能:1.N个数的最大公约数和最小公倍数 *2.已知正整数a0,a1,b0,b1,设某未知正整数x满足:*(1)x和a0的最大公约数为a1;*(2)x和b0的最小公倍数为b1;*输入数据 保证a0能被a1整除,b1能被b0整除。*对于每组数据:若不存在这样的x,请输出0;若存在这样的x,请输出满足条件的x的个数; *对于两个整数,它们两个的乘积等于它们的最大公约数和最小公倍数的乘积。* 使用辗转相除法求最大公约数 */ #include "iostream"using namespace std;//N个数的最大公约数 int GCD(int m,int n){   	//递归写法 	if(n == 0)	{   		return m;	}	return GCD(n,m%n);	/*	//迭代写法            while(n != 0){            int t = n;            n= m % n;            m = t;        }        return m;    }	*/}//N个数字的最小公倍数 int LCM(int m,int n){   	return (m*n)/GCD(m,n);}//判断输入数据的正确性 int inspect(int *array,int number){   	for(int i = 0;i<number;i++){   		if(array[i] == 0 || (int)array[i] != array[i])		{   			system("cls"); 			cout<<"输入数据中包含0或者非法字符,请重新输入"<<number<<"个数字:"<<endl;			cin.clear();                          //恢复cin状态             cin.sync();   //清除缓冲区的数据流 			return 0; 		}	}	return 1;}int Hanson(int line_number){   	int number = 0;	int count[line_number];	while(line_number--) 	{           int a0,a1,b0,b1;                //对输入数据进行判断         while(1)        {           	cin>>a0>>a1>>b0>>b1;        	if(a0%a1 != 0 || b1%b0 != 0)        	{           		cout<<"输入数据有误,请重新输入这组数据!"<<endl;        		continue;			}			else{   				break;			}		}                int p=a0/a1,q=b1/b0,ans=0;        for(int x=1;x*x<=b1;x++)             if(b1%x==0)			{     //x是b1的一个因子                 if(x%a1==0&&GCD(x/a1,p)==1&&GCD(q,b1/x)==1) ans++;                int y=b1/x;      //y是另一个因子                 if(x==y) continue;                 if(y%a1==0&&GCD(y/a1,p)==1&&GCD(q,b1/y)==1) ans++;            }            count[number] = ans;            number++;    }    for(int i = 0;i<number;i++)    {       	cout<<count[i]<<endl;	}}int main(){   	int choose_number;  // 功能选择序号 	int number; //输入数字的个数;	while(1)	{   				cout<<"1.求N个数的最大公约数和最小公倍数\n2.Hankson的“逆问题”\n请输入你的功能选择序号:";		std::cin>>choose_number;		if(cin.fail() || choose_number != 1 && choose_number != 2)            //cin.fail()  判断cin状态               		{   			system("cls");			cout<<"输入有误,请重新输入你的选择!"<<endl;                                 cin.clear();                          //恢复cin状态             cin.sync();   //清除缓冲区的数据流 			        	}                         else                         {                                                                 break;                        	}	} 	if(choose_number == 1)		{          		int flag = 0; //用于判断        		system("cls");			cout<<"请输入你要判断数字的个数:"<<endl; 			cin.clear();                          //恢复cin状态             cin.sync();   //清除缓冲区的数据流			cin>>number;			int array[number];			cout<<"请输入"<<number<<"个数字(两个数字之间用空格隔开):"<<endl;			while(!flag)			{   				//输入数据 				for(int i = 0;i<number;i++)				{   					cin>>array[i];				}								//判断输入数据是否准确 				flag = inspect(array,number);				}			int lcm = array[0];	//存放最小公倍数			int gcd = array[0]; //存放最大公约数 			for(int i = 0;i<number;i++)			{   				lcm = LCM(lcm,array[i]);				gcd = GCD(gcd,array[i]);			}			cout<<"这些数据中最大公约数为:"<<gcd<<endl;			cout<<"这些数据中最小公倍数为:"<<lcm<<endl;		}		else		{   			system("cls");			cout<<"Hanson“逆问题”"<<endl;			int line_number;    		cin>>line_number;    		Hanson(line_number);        							 		}			return 0;}

总结

1.定义了整形数line_number,如果输入字母或者其他非法字符,就会出现乱码现象,并且无法操作,只能终止。
解决方法:使用cin.fail()判断cin的状态,如果出现乱码现象,可以使用cin.clear()恢复cin的状态,并使用cin.sync(); //清除缓冲区的数据流 。这样就可以提示输入错误,重新输入。
2.对于动态数组长度问题,这里采用的还是输入数组长度,然后定义数组长度。但在VC环境中会报错。E0028。后面作业中可以使用Vector。vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
对于解决Hanson“逆问题”的问题上,之前写的代码所占内存过于大。而且对于换行存数据并计算X的个数存在一点问题。如果只测一行数据,可以测。但如果测第二组数据就会显示的结果是正确的结果减一。第三个结果就溢出了。所以借鉴了CSDN上的文章
链接: .

转载地址:http://yuve.baihongyu.com/

你可能感兴趣的文章
蹒跚来迟:新版博客后台上线公测
查看>>
上周热点回顾(9.16-9.22)
查看>>
上周热点回顾(11.4-11.10)
查看>>
[网站公告]11月26日00:00-04:00阿里云RDS升级
查看>>
[网站公告]又拍云API故障造成图片无法上传(已恢复)
查看>>
上周热点回顾(12.16-12.22)
查看>>
云计算之路-阿里云上:对“黑色30秒”问题的猜想
查看>>
云计算之路-阿里云上:“黑色30秒”走了,“黑色1秒”来了,真相也许大白了
查看>>
云计算之路-阿里云上:奇怪的CPU 100%问题
查看>>
云计算之路-阿里云上:2014年6月12日12点IIS请求到达量突降
查看>>
上周热点回顾(6.9-6.15)
查看>>
上周热点回顾(6.16-6.22)
查看>>
上周热点回顾(6.23-6.29)
查看>>
上周热点回顾(10.20-10.26)
查看>>
上周热点回顾(2.16-2.22)
查看>>
上周热点回顾(3.2-3.8)
查看>>
.NET跨平台之旅:借助ASP.NET 5 Beta5的新特性显示CLR与操作系统信息
查看>>
上周热点回顾(7.27-8.2)
查看>>
上周热点回顾(9.28-10.4)
查看>>
上周热点回顾(3.28-4.3)
查看>>