1. 程式人生 > >[質因數分解]UVa10791 Minimum Sum LCM

[質因數分解]UVa10791 Minimum Sum LCM

uva10791 系列 i++ 一個 scan can 證明 輸出 題目

題目大意

輸入整數n (1<=n<2^31),求至少兩個正整數,使得它們的最小公倍數為n,且這些整數的和最小,輸出最小的和。

(LRJ小紫書P317頁例題)

思考

看LRJ的分析沒怎麽看懂,隨手搜了一篇題解。發現了一個講的不錯的,讓我恍然大悟。

題解地址

首先假設我們知道了一系列數字a1,a2,a3……an,他們的LCM是n,那麽什麽時候他們是最優解呢,當他們兩兩互質的時候。

簡單證明一下:

設兩個正整數為a,b (a<=b) 其gcd(a,b)=n lcm(a,b)=m sum = a + b

如果n!=1(a,b不互質) 那麽我們在m不變的情況下 優化一下 a = a / n

那麽a變小後,sum必然減少。

那我們怎麽保證兩兩互質呢?方法其實很簡單,直接分解質因子。

所以我們已經得到了這個問題的解法

1.將一個數分解成質因子,將相同的因子乘起來作為一個處理後的因子

2.將處理後得到的多個因子直接相加就是答案

3.因為題目說只要需要兩個數字,所以對於1和素數我們需要小心。對於素數,我們只能分解出一個因子就它自己,對於1一個因子都分解不出來(我們不把1當做因子),他們的答案都是n+1,因為只有1和n的LCM是n 。

#include <cstdio>
#include <iostream>
#include 
<cmath> typedef long long ll; ll f[233],Count,n,ans; void init(ll n){ ll m = (ll)sqrt(n+1); Count=0; for(ll i=2;i<=m && n>1 ;i++){ if(!(n%i)){ ll fac=1; while(!(n%i) && n>1){ fac*=i; n
/=i; } f[Count++] = fac; //printf("Run\n"); } } if(n>1) f[Count++]=n; } int main(){ int Case=0; while(scanf("%d",&n) && n!=0){ ans=0; init(n); //printf("%d\n",Count); if(!Count || Count==1) ans=n+1; else for(int i=0;i<Count;i++) ans+=f[i]; printf("Case %d: %lld\n",++Case,ans); } return 0; }

[質因數分解]UVa10791 Minimum Sum LCM