[質因數分解]UVa10791 Minimum Sum LCM
阿新 • • 發佈:2017-06-30
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