Uva 10791 - Minimum Sum LCM(唯一分解定理)

题目链接 https://vjudge.net/problem/UVA-10791

【题意】

        输入整数(n>=1, n<2^31),求至少两个整数,使得他们的最小公倍数为n, 且这些整数的和最小, 输出最小和

【思路】

        假设正整数x是c1,c2...cm的LCM,那么在什么情况下sum{ci | 1<=i<=m}最小?答案是当c1,c2...cm互素的时候,比方说只有两个数a,b. lcm(a,b)=a*b/gcd(a,b),那么如果a,b不是互素的,也就是说gcd(a,b)!=1,那么可以让c=a/gcd(a,b)作为一个新的数,这样lcm(a,b)=c*b,且c+b<a+b,和变得更小了. 由数论唯一分解定理,正整数x=p1^a1*p2^a2*p3^a3...pn^an,那么pi^ai求和即为结果,注意有几种特殊情况。

        (1)n=1,1=1*1,应输出2

        (2)n为素数,n=n*1,应输出n+1

        (3)n只有一个素因子即n=p1^a1,应输出 n+1

        (4)用long long,因为n=0x7fffffff是素数,输出n+1会使int溢出

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

bool isprime(ll x) {
	if (x < 2) return 0;
	if (x == 2) return 1;
	if (x & 1 == 0) return 0;
	int m = sqrt(x) + 0.5;
	for (int i = 2; i <= m; ++i) {
		if (x % i == 0) return 0;
	}
	return 1;
}

int main() {
	ll n;
	int kase = 0;
	while (scanf("%lld", &n) == 1 && n) {
		if (1 == n) {
			printf("Case %d: 2\n", ++kase);
			continue;
		}
		if (isprime(n)) {
			printf("Case %d: %lld\n", ++kase, n + 1);
			continue;
		}

		int cnt = 0;//cnt记录素因子的个数
		ll ans = 0;
		int m = sqrt(n) + 0.5;
		for (int i = 2; i <= m; ++i) {
			if (n % i == 0) {
				int tmp = 1;
				++cnt;
				while (n % i == 0) {
					tmp *= i;
					n /= i;
				}
				ans += tmp;
			}
		}

		if (n > 1) ans += n;//最后一个素因子可能还没被分解,比如n=10时
		if (cnt == 1 && n == 1) ++ans;
		printf("Case %d: %lld\n", ++kase, ans);
	}
	return 0;
}

 

 

 

 

 

posted @ 2018-01-29 10:53  不想吃WA的咸鱼  阅读(139)  评论(0编辑  收藏  举报