题目
问题描述
已知一个正整数N,问从1~N中任选出三个数,他们的最小公倍数最大可以为多少。
输入格式
输入一个正整数N。
输出格式
输出一个整数,表示你找到的最小公倍数。
样例输入
9
样例输出
504
数据规模与约定
1 <= N <= 106。
想法
利用贪心的思想思考这个问题,贪心思想即在对问题求解时,总是做出在当前看来时最好的选择。在求解这个问题时,由于要求最大的最小公倍数,所以自然应当从最大的三个数开始讨论,在这里,我们现引入几个定理。
(1)相邻两个自然数互质;
(2)相邻两个奇数互质;
(3)两个整数的乘积等于其最大公约数与最小公倍数的乘积。
现在开始讨论:
(1)如果N为奇数,则 N N-1 N-2 为 奇-偶-奇,对于N与N-1及N-1与N-2,由上述定理(1),可知互质,N与N-2由上述定理(2)可知互质。两两互质的三个数,根据互质的概念,它们公约数只有1,此时结合定理(3),能够判断三者之积即为最大的最小公倍数。
(2)如果N为偶数,则 N N-1 N-2 为 偶-奇-偶,同(1),N与N-1及N-1与N-2互质,但是对于N与N-2,N为偶数,N-2也是偶数,由这样会导致N与N-2的最小公倍数减半,不值得。因此再利用贪心的思想(我想让三个不同的数尽可能大,所以把最小的往小调),把N-2调成N-3,此时就可以避免这种情况。
(3)但是,对于N N-1 N-3,如果N%3==0,则(N-3)%3==0,因此会导致二者最大公约数变为1/3,这时要讨论这种情况,如果是这种情况,那么要调整N为N-2,此时与(1)同类型。
实现
#include<iostream>
using namespace std;
int main(void)
{
long long N;
long long ans;
cin>>N;
if(N%2){
ans=N*(N-1)*(N-2);
}
else{
if(N%3) ans=N*(N-1)*(N-3);
else ans=(N-1)*(N-2)*(N-3);
}
cout<<ans;
return 0;
}
在实现中,我一开始忽略了一个小细节,就是对N的类型,如果设置为int,即使N输入不会溢出,但是在运算时N*(N-1)*(N-2)会超出int范围,虽然结果声明的变量是long long,但是右边的表达式还是会按照int处理。
我刚刚接触这些,才疏学浅,望各位高手指教!