Lowest Common Multiple Plus(这是数论算法中的基础算法程序)
Problem Description
求n个数的最小公倍数。
Input
输入包含多个测试实例,每个测试实例的开始是一个正整数n,然后是n个正整数。
Output
为每组测试数据输出它们的最小公倍数,每个测试实例的输出占一行。你可以假设最后的输出是一个32位的整数。
Sample Input
2 4 6
3 2 5 7
Sample Output
12
70
问题链接:HDU2028 Lowest Common Multiple Plus。
问题简述:(略)
问题分析:最大公约数和最小公倍数是数论中的两个重要概念。以及求多个数的最大公约数和最小公倍数。
程序说明:
计算最小公倍数时,使用带参数的宏定义,而不是使用函数。这样做程序会略微快一些,因为省去了函数的调用、返回和参数传递。
参考链接:多个数求最小公倍数。
代码如下:
第一次的代码:
#include <stdio.h>
#include <stdlib.h>
int Gcd(int m,int n);
int main()
{
int n,i;
while (scanf("%d",&n) != EOF)
{
if (n == 1)
{
int a;
scanf("%d",&a);
printf("%d\n",a);
}
else
{
int gcd;
int sum;
int *a = (int *)malloc(sizeof(int) * n);
for (i = 0;i < n;i ++)
scanf("%d",&a[i]);
gcd = Gcd(a[0],a[1]);//具体看参考链接
sum = a[0] / gcd * a[1];
for (i = 2;i < n;i ++)
{
gcd = Gcd(sum,a[i]);
sum = sum / gcd * a[i];
}
printf("%d\n",sum);
free(a);
}
}
return 0;
}
int Gcd(int m,int n)
{
if (m % n == 0)
return n;
else
return Gcd(n,m % n);
}
改进后的:
#include <stdio.h>
#define lcm(a, b) a / gcd(a, b) * b//带参数的宏定义,a*b会超int64,会出现RE。
long gcd(long m, long n)
{
while(n)
{
long temp = m % n;
m = n;
n = temp;
}
return m;
}
int main(void)
{
int n, lcmval, val;
while(scanf("%d", &n) != EOF)
{
// 先读入一个数
scanf("%d", &lcmval);
// 读入n-1个数,同时计算最小公倍数
while(n --) {
scanf("%d", &val);
lcmval = lcm(lcmval, val);
}
printf("%d\n", lcmval);
}
return 0;
}
递归求最大公约数:
long gcd(long m,long n)//利用了辗转相除法,所以不用考略m < n的情况。
{
if (m % n == 0)
return n;
else
return gcd(n,m % n);
}
总结:
1.c语言要输入输出一个32位的数字
(1)看看你的sizeof(int)
等于多少了,如果结果为4,那么就是int就足够拉,打印时为%d;
如果是sizeof(long) == 4
,那么就使用long,打印%ld。
(2)如果是相当大的数字,那么需要自行编码实现特殊的数据类型了,可以用字符串/链表之类的模仿,打印输出也是特殊定制的。
2.多个数的最大公约数算法
(1)自然而然会想到用逐轮用2个数计算,将上一步的最大公约数与下一个数继续计算,直到计算完所有数。
(2)上面的算法比较麻烦,因为不断调用内部有多次循环的 gcd 算法。其实,根据辗转相除法,我们可以这样做:
1.对这一组数进行排序(从大到小)
2.对每两个相邻的两个数进行如下操作:设相邻的两个数为A和B(A在前,因为已经排序,所以A > B),如果A = n * B(n为整数),也就是A能够被B整除,那么就令A = B;如果A不能被B整除则令A = A % B。
3.重复上面两步,直到数组中每个数都相等,则最大公约数就为这个数。