紫书10-4 最小公倍数的最小和(Minimum Sum LCM ) UVA10791

题意:给一个整数n,求至少两个各不同的正整数,让它们的最小公倍数为n,且这些整数的和最小.
回顾下紫书的一些知识点。
我们知道,lcm(a,b)=a*b/gcd(a,b).但这还不够。
事实上,gcd是对a与b做唯一分解后,对每个质因子取最小值相乘,而lcm就是对每个质因子取最大相乘。
在这里插入图片描述
整了这么多,如何让这个数的和最小呢?先考虑极限极限情况,假设就是n和1,这个时候就是n+1.那么怎么让它变小呢?没错!就是唯一分解,只要把lcm(a,b)中的一个数拿出来单独作为一个新的整数,会比之前小很多。
假设不拿之前是n吧.拿了之后是n除以这个因子再加上这个因子!贪心地想每个唯一分解出来的素数作为新的正整数时,和就是最小的!那么问题就转化为求n的唯一分解式子里每个因子的求和。
注意,当n是一个素数或者仅有一个因子的时候,没有足够的因子满足题目的不同正整数,要“借”一个“1”,所以是n+1.
记得再构造一个素数表.
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e7+2;
int prime[maxn];int cal[maxn];
int cnt=0;bool vis[maxn];
void pre(int n){
	memset(vis,0,sizeof(vis));
	for(int i=2;i<=n;i++){
		if(!vis[i]) prime[++cnt]=i;
		for(int j=1;j<=cnt;j++){
			if(prime[j]*i>n) break;
			vis[prime[j]*i]=1;
			if(i%prime[j]==0) break;
		}
	}
}
int main(){
	int n;int kase=0;
	pre(10000000); //make the prime table
	while(scanf("%d",&n)==1&&n){
		long long ans=0;
		memset(cal,0,sizeof(cal));
		int m=n;vector<int> v;
		for(int i=1;i<=cnt;i++){
			int first=0;
			while(n%prime[i]==0) {
				n/=prime[i];cal[prime[i]]++;
				if(!first) {
					v.push_back(prime[i]);first=1;
				}
			}
		}
		for(int i=1;i<=cnt;i++){
			if(cal[prime[i]]>0){
				ans+=pow(prime[i],cal[prime[i]]);
			}
		}
		if(v.size()==0||v.size()==1) printf("Case %d: %ld\n",++kase,m+1);
		else printf("Case %d: %lld\n",++kase,ans);
	}
return 0;}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

minato_yukina

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值