正整數分解使得乘積最大問題(轉載)
轉載:https://blog.csdn.net/xiaoquantouer/article/details/70142739
一、問題描述
設n是一個正整數。現在要求將n分解為若干個自然數之和,使得自然數的成績最大。輸出這個最大的乘積。
要求:
(1)要求這些自然數互不相同
(2)要求這些自然數可以是相同的
二、問題分析:
這類題一開始需要我們手寫幾個數來看看規律。先做第一問,要求自然數互不相同。從5開始寫起,5=2+3,6=2+4,7=3+4,8=3+5,9=2+3+4,10=2+3+5,11=2+4+5
發現規律如下:
(1)儘量使得元素是連續的。
(2)如果有多出來的,從後往前均勻分配到各個元素。考慮到一種特殊情況,當多出來的數比前面已有元素的個數大1時(比如8的情況),先給已有元素的最大元素加1,然後再均勻分配到每個元素。
下面舉個栗子,看看攜程實習生招聘筆試的這道題:
題目描述:乘積最大
有一個整數n,將n分解成若干個不同自然數之和,問如何分解能使這些數的乘積最大,輸出這個乘積m。
輸入:
一個整數,不超過50
輸出
一個整數
樣例輸入
15
樣例輸出
144
1 #include<iostream> 2 #include<vector> 3 using namespacestd; 4 5 int main(){ 6 int num; 7 while(cin>>num){ 8 intflag[100] = {0}; 9 int k=2; 10 int i=0; 11 while(num >= k){ 12 //從2開始分解,依次分解為2,3,4,5...連續的元素 13 flag[i++] = k; 14 num -= k; 15 k++; 16 } 17 if(num > 0){ 18 //說明有剩餘的 19 if(num == flag[i-1]){ 20 //說明這時候剩餘的數正好比已有的元素個數多1,所以要先給最後一個元素加1 21 flag[i-1]++; 22 num--; 23 } 24 for(int j=i-1;j>=0 &&num>0;j--){ 25 flag[j] ++; 26 num--; 27 } 28 29 } 30 int result = 1; 31 for(int j = 0;j<i;j++){ 32 result *= flag[j]; 33 } 34 cout<<result<<endl; 35 }//while 36 return 0; 37 }
對於第二問,對於元素可以是相同的
仍然是通過手寫幾個數檢視一下規律:4=2+2,5=2+3,6=3+3,7=3+2+2,8=3+3+2,9=3+3+3。
發現規律如下:
(1)元素不會超過4,因為4=2+2,又可以轉化為2的問題,而5=2+3,5<2*3,所以5總能分解成2和3。
(2)儘可能多分解出3,然後分解出2,不要分出1。
考慮任意一個數,除以3之後的結果有以下3種:
(1)能被3除斷,那麼就分解為3+3+...+3的情況即可。例如9=3+3+3。
(2)被3除餘1,分解為3+3+...+3+2+2或者3+3+...+3+4的情況,例如10=3+3+2+2
(3)被3除餘2,分解為3+3+...+3+2的情況,例如11=3+3+3+2。
1 #include<iostream> 2 #include<math.h> 3 usingnamespace std; 4 5 int main(){ 6 int num; 7 while(cin>>num){ 8 if(num % 3 == 0){ //考慮被3整除的情況 9 cout<<pow(3,num/3)<<endl; 10 continue; 11 } 12 int flag[100] = {0}; 13 int i=0; 14 while(num != 2 && num != 4){ 15 //如果不能被3整除,那麼除3必餘1或者2,而餘1和4是同樣的情況,這裡取4是因為這種情況下最後是兩個2, 16 //取4就可以直接把4分解為2+2 17 flag[i++]=3; 18 num-=3; 19 } 20 while(num){ //餘2和1的情況,餘2就是1個2,餘1就是2個2,所以前面才會判斷是否等於4,這樣就可以化為2個2 21 flag[i++] = 2; 22 num-=2; 23 } 24 int result = 1; 25 for(int j=0;j<i;j++){ 26 result *= flag[j]; 27 } 28 cout<<result<<endl; 29 }//while 30 return 0; 31 }