题意:
输入正整数n(n<=2^31-1),找到至少两个正整数,使得他们的LCM为n,并且和是最小。
分析:
这题昨天做的,WA的我一脸懵逼QAQ,刚刚又看了下,原来我看成了是两个整数,把至少这俩字漏看了QAQ。
如果是至少两个数的话,那么就非常简单了,只需要把质因数(次方)求和即可(因为可以是很多数的LCM)
此题需注意的情况:
(1)当N = 1时,应输出2(1*1=1,sum=1+1=2);
(3)当只有单质因子时,sum=质因子相应次方+1;
(4)当N=2147483647时,它是一个素数,此时输出2147483648,但是它超过int范围,应考虑用long long。
代码:
typedef long long ll;
ll num[33];
int main()
{
ll n;
int cas=0,tot;
while(~scanf("%lld",&n)&&n){
printf("Case %d: ",++cas);
if(n==1){
puts("2");continue;
}
tot=0;
for(ll i=2;i*i<=n;i++){
if(n%i==0){
num[tot]=1;
while(n%i==0){
num[tot]*=i;
n/=i;
}
tot++;
}
}
if(n>1)num[tot++]=n;
if(tot<2){
printf("%lld
",num[0]+1);continue;
}
ll ans=0;
for(int i=0;i<tot;i++)ans+=num[i];
printf("%lld
",ans);
}
return 0;
}
把题目变一下:找到两个正整数,使得他们的LCM为n,并且和是最小。
分析:
因为要求是两个整数的LCM,所以要把分解得到的质因子(次方)分成两组,两组求积得到两个数,使这两个数的和最小。那怎么分组呢?显然让两组的积尽量的接近可以使所得和最小,那么用优先队列去维护一下分组就行。
typedef long long ll;
ll num[33];
int main()
{
ll n;
int cas=0,tot;
while(~scanf("%lld",&n)&&n){
printf("Case %d: ",++cas);
if(n==1){
puts("2");continue;
}
tot=0;
priority_queue<ll,vector<ll>,greater<ll> >q;
for(ll i=2;i*i<=n;i++){
if(n%i==0){
num[tot]=1;
while(n%i==0){
num[tot]*=i;
n/=i;
}
tot++;
}
}
if(n>1)num[tot++]=n;
if(tot<2){
printf("%lld
",num[0]+1);continue;
}
for(int i=0;i<tot;i++)q.push(num[i]);
while(q.size()>2){
ll a1=q.top();q.pop();
ll a2=q.top();q.pop();
q.push(a1*a2);
}
ll a1=q.top();q.pop();
ll a2=q.top();q.pop();
printf("%lld
",a1+a2);
}
return 0;
}