● 题目名称
<1>求N个数的最大公约数和最小公倍数
<2>计算出Hankson的“逆问题”的答案
● 题目分析
<1>求N个数的最大公约数和最小公倍数:可以先求出第一个数和第二个数的最大公约数和最小公倍数,再将这个最大公约数和最小公倍数与下一个数计算出新的最大公约数和最小公倍数,以此类推
<2>计算出Hankson的“逆问题”的答案:先输入组数,再根据组数以每组4个数循环输入,然后判断输入的四个数是否满足条件,接着再调用计算两个数的最大公约数和最小公倍数的函数,判断x是否满足条件,若满足,则累加,最后输出累加的结果
● 算法构造
● ● 求N个数的最大公约数和最小公倍数
<1>输入要计算最大公约数和最小公倍数的整数个数
<2>循环输入整数
<3>调用函数,求出这些整数的最大公约数和最小公倍数
<4>先计算出两个数的最大公约数(最小公倍数),再用该最大公约数(最小公倍数)和下一个数求最大公约数(最小公倍数),以此类推
<5>输出这些整数的最大公约数和最小公倍数
● ● 计算出Hankson的“逆问题”的答案
<1>输入组数
<2>每组输入四个数,判断是否满足第一个数能被第二个数整除,第三个数能被第四个数整除的条件
<3>循环依次输入各组,每组4个数
<4>判断输入的4个数是否满足第一个数能被第二个数整除,第三个数能被第四个数整除的条件
<5>循环计算有多少个满足条件的数,调用计算两个数的最大公约数和最小公倍数的函数,判断x是否满足条件
<6>输出累加的数
● 算法实现
#include<stdio.h>
//辗转相除法求两个数的最大公约数
int max1(int a,int b)
{
int temp;
if(a<b) //若存在a小于b的情况,则交换数值
{
temp=a;
a=b;
b=temp;
}
while(b!=0) //直到b为0,通过赋值得到最大公约数为a的值
{
temp=a%b; //temp为余数
a=b; //将b的值赋给a
b=temp; //将余数temp的值赋给b
}
return a;
}
//求n个数的最大公约数
int max2(int a[],int n)
{
int x=a[0],y=a[1],z=0;
z=max1(x,y); //先计算出两个数的最大公约数,再用该最大公约数和下一个数求最大公约数,以此类推
for(int i=2;i<n;i++)
z=max1(z,a[i]);
return z;
}
//求两个数的最小公倍数
int min1(int a,int b)
{
int max1(int a,int b); //自定义函数返回值类型
int temp;
temp=max1(a,b); //再次调用自定义函数,求出最大公约数
return (a*b/temp); //返回最小公倍数到主调函数处进行输出
}
//求n个数的最小公倍数
int min2(int a[],int n)
{
int x=a[0],y=a[1],z=0; //与n个数的最大公约数同理
z=min1(x,y);
for(int i=2;i<n;i++)
z=min1(z,a[i]);
return z;
}
void main()
{
int n=0,x=0,max=0,min=0,b,sum=0,i=0;
int c[4];
int a[]={0};
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
printf("* 1.输入n个你想计算最大公约数的正整数并计算. *\n");
printf("* 2.计算出Hankson的“逆问题”的答案. *\n");
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
printf("请选择你想要进行的操作:\n");
scanf("%d",&x);
while(x<1||x>2)
{
printf("没有这个选项!请重新输入:\n");
scanf("%d",&x);
}
switch(x)
{
case 1:
printf("请输入你想要计算的整数个数(大于1):");
scanf("%d",&n); //输入要计算最大公约数和最小公倍数的整数个数
printf("请依次输入整数:\n");
for(i=0;i<n;i++)
scanf("%d",&a[i]); //循环输入整数
max=max2(a,n); //调用函数,求出这些整数的最大公约数
min=min2(a,n); //调用函数,求出这些整数的最小公倍数
printf("这些数的最大公约数为:%d\n",max);
printf("这些数的最小公倍数为:%d\n",min);
break;
case 2:
printf("请输入数据的组数:");
scanf("%d",&b); //输入组数
printf("每组输入四个数,要求:保证第一个数能被第二个数整除,第三个数能被第四个数整除:\n");
for(;b>0;b--) //循环依次输入b个组
{
for(i=0;i<4;i++) //每组4个数
{
scanf("%d",&c[i]);
}
if(c[0]%c[1]!=0||c[3]%c[2]!=0) //判断输入的4个数是否满足第一个数能被第二个数整除,第三个数能被第四个数整除的条件
{
printf("输入不符合条件,请重新输入:\n");
for(i=0;i<4;i++)
{
scanf("%d",&c[i]);
}
}
for(int y=0;y<=c[3];y++) //循环计算有多少个满足条件的数
{
if(max1(y,c[0])==c[1]&&min1(y,c[2])==c[3]) //调用计算两个数的最大公约数和最小公倍数的函数,判断y是否满足条件
sum++;
}
printf("一共有%d个数满足条件\n",sum);
sum=0; //累加sum初始化
}
}
}
● 经验归纳
● ● 遇到的问题
<1>习惯了计算两个数的最大公约数和最小公倍数,对N个数迷茫了…
<2>最大公约数和最小公倍数计算有误
<3>提高要求要输入的那四个数的限制条件运用不当,审题不清,导致频繁出错
<4>在一次循环之后未将累加的值初始化,导致下一次循环完毕后的结果有误
● ● 心得体会
以前都是计算两个数的最大公约数和最小公倍数,这次要计算n个数的最大公约数和最小公倍数,我其实运用的还是计算两个数的那个思想,就是加入了函数调用。
感觉自己有时候还挺粗心的(也可能是代码敲久了有点晕hhh),还有就是提高要求把我卡住了。。完全不知道逆着怎么求…查了一些资料,然后和一起去图书馆敲代码的同学讨论了一下,大体有思路了,但只要写程序就有错误。。。。
失误挺多的,希望自己能在以后的程序生涯里越来越棒,小细节都可以注意到~~~