2019.3.26HDOJ-2028求最小公倍数的思考,辗转相除法的证明

版权声明:那啥,咱一个萌新写的东西没啥价值。但是也要打个招呼吧…… https://blog.csdn.net/Miaplacidus/article/details/88817636

这道题当时盯着看了十分钟也没有一点头绪,还是我太菜了,于是上网寻找求最小公倍数方法

题目

Problem-2028
Problem Description
求n个数的最小公倍数。

Input
输入包含多个测试实例,每个测试实例的开始是一个正整数n,然后是n个正整数。

Output
为每组测试数据输出它们的最小公倍数,每个测试实例的输出占一行。你可以假设最后的输出是一个32位的整数。

Sample Input
2 4 6
3 2 5 7

Sample Output
12
70

方法

查阅WIKI百科可知,最小公倍数=两个整数的/这两个数的最大公因数
https://zh.wikipedia.org/wiki/最小公倍數#与最大公因数之关系
这个公式我还没搞明白……
先求最大公因数,可以使用辗转相除法或更相减损术来求。
http://www.cnblogs.com/santiego/p/9568208.html

辗转相除法的证明

为什么除数和余数的最大公约数就是被除数和除数的最大公约数?
试证:被除数A与除数B,且A>B,和它们的余数R的最大公约数相同
证明:由题意可设, A = q B + R q N + 0 < R < B A=qB+R(q∈N+),0<R<B
A A B B 最大公约数为 d d ,记为 d = ( A , B ) d=(A,B)
先证d为B与R的公因数
m , n N + m,n∈N+ ,使 A = m d , B = n d A=md,B=nd
R = A q B = m d q n d = d ( m q n ) R=A-qB=md-qnd=d(m-qn)
R R 能被 d d 整除,即 d d R R 的因数
再证 d d B B R R 的最大公因数,即证 d = ( B , R ) d=(B,R)
反证法:假设存在 D D ,使 ( B , R ) = D > d (B,R)=D>d
A = q B + R ∵A=qB+R
D能整除 A A D D 能整除 B B
D ∴D 能整除 ( A , B ) = d (A,B)=d
推出 D d D≤d ,与假设矛盾
不存在 ( B , R ) = D > d (B,R)=D>d
d d B B R R 的最大公因数
( A , B ) = ( B , R ) = d ∴(A,B)=(B,R)=d
可以看出该性质可以传递
( A , B ) = ( B , A % B ) = ( A % B , B % ( A % B ) ) = = ( d , 0 ) (A,B)=(B,A\%B)=(A\%B,B\%(A\%B))=…=(d,0)
所以当最后余数为0时,除数即为最大公约数 d d
给出 A > B A>B ,求最大公因数,可以得递推公式
f ( A , B ) = { A B = 0 f ( B , A % B ) B > 0 f(A,B)= \begin{cases} A & B = 0 \\ f(B,A\%B)& B>0 \end{cases}

证明最小公倍数=两数之积/最大公约数

(这部分思路参考了一位数学系的同学,他跟我说不知道咋证就显然)
d = ( A , B ) , M d=(A,B),M A B A,B 最小公倍数,记 M = [ A , B ] M=[A,B]
A = m d , B = n d , A=md,B=nd, m , n N + m,n∈N+
存在 M = p A = q B , p , q N + ( p , q ) = 1 M=pA=qB ,且p,q∈N+,(p,q)=1
M ∵M 能被 A = m d A=md 整除, M M 能被 B = n d B=nd 整除, ( m , n ) = 1 (m,n)=1
显然 m n d mnd A , B A,B 公倍数,设 N N A , B A,B 的任一公倍数
m n d mnd 一定能整除 N N ,推得 m n d mnd A A B B 的最小公倍数
[ A , B ] = m n d = ( A B ) / d ∴[A,B]=mnd= (A*B)/d

代码

#include<stdio.h>
long long gcd(long long a,long long b);
long long lcm(long long a,long long b);
int main(void)
{
	int n;
	long long next;
	while(scanf("%d",&n)==1){
		long long commul=1;
		while(n-->0){
			scanf("%lld",&next);
			commul=lcm(commul,next);
		}
		printf("%lld\n",commul);
	}
	return 0;
}
long long gcd(long long a,long long b)//返回a,b最大公约数 
{
	long long r;
	if(a<b){
		r=b;
		b=a;
		a=r;
	}
	while((r=a%b)!=0){
		a=b;
		b=r;
	}
	return b;
}
long long lcm(long long a,long long b)//返回a,b的最小公倍数 
{
	long long multi=a*b;
	return multi/gcd(a,b);
}

按照题目的意思,进行乘法运算一定会溢出。
之前两次使用强制转换怎么改还是WA,一怒之下全部换成了long long,终于AC了

Run ID Submit Time Judge Status Pro.ID Exe.Time Exe.Memory Code Len. Language Author
28719269 2019-03-27 18:40:05 Accepted 2028 15MS 1692K 608 B C Overstars
28719245 2019-03-27 18:38:24 Wrong Answer 2028 0MS 1696K 588 B C Overstars
28719220 2019-03-27 18:36:12 Wrong Answer 2028 31MS 1700K 514 B C Overstars

也不知道这道题花了这么多时间值不值。
好了,今天晚上去图书馆把DP入个门……
大物也得稍微自学下……

2019年3月27日18点44分

猜你喜欢

转载自blog.csdn.net/Miaplacidus/article/details/88817636