传送门:https://cn.vjudge.net/problem/UVA-10791
题意:
输入整数n(1<=n<
),求至少两个正整数n,使得它们的最小公倍数为n,且这些整数的和最小。输出最小的和。
分析:
用唯一分解定理即可。设唯一分解式为
···,不难发现每个
作为一个单独的整数时最优。
如果就这样匆匆编写程序,可能会掉入陷阱。因为有好几个特殊情况要处理:
1、n==1时答案为1+1=2。
2、n只有一种因子时需要加个1。
3、注意n=
时不要溢出。
4、求解唯一分解式时可能遇到n为大素数,此时注意求解完后n是否为1!!!
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 2e5 + 5;
bool isprime[N];
int cntp=0, prime[N/10], phi[N], e[N/10];
void init(){
memset(isprime, 1, sizeof(isprime));
isprime[0] = isprime[1] = 0; cntp = 0;
phi[1] = 1;
for(int i = 2; i < N; ++i){
if(isprime[i]){
prime[++cntp] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= cntp && i * prime[j] < N; ++j){
isprime[i * prime[j]] = 0;
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j];
break ;
}
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
ll qsm(ll a,ll b){
ll res=1;
while(b){
if(b&1)
res*=a;
a*=a;
b>>=1;
}
return res;
}
int main(){
init();
ll n,k=1,ans,num;
while(~scanf("%lld",&n)&&n){
if(n==1){
ans=2;
}else{
ans=num=0;
memset(e,0,sizeof(e));
for(int i=1;i<=cntp;i++){
while(n%prime[i]==0){
n/=prime[i];
e[i]++;
}
if(e[i]>0){
ans+=qsm(prime[i],e[i]);
num++;
}
if(n==1) break;
}
if(n!=1){
num++;
ans+=n;
}
if(num==1)
ans++;
}
printf("Case %lld: %lld\n",k++,ans);
}
return 0;
}