题目链接 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;
}