UVa 10791 和最小的LCM (质因数分解)

题意:

输入正整数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\n",num[0]+1);continue;
        }
        ll ans=0;
        for(int i=0;i<tot;i++)ans+=num[i];

        printf("%lld\n",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\n",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\n",a1+a2);
    }
    return 0;
}

转载于:https://www.cnblogs.com/01world/p/5762805.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值