傳送門: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;
}