正整數最優分解問題

1、 題目

   最優分解問題算法

2、 問題描述

設n是一個正整數。如今要求將n分解爲若干互不相同的天然數的和,且使這些天然數的乘積最大。ide

算法設計:對於給定的正整數n,計算最優分解方案。google

數據輸入:由文件 input.txt 提供輸入數據。文件的第一行是正整數n。spa

結果輸出:將計算出的最大乘積輸出到文件output.txt。設計

輸入文件示例code

輸出文件示例blog

input.txtip

output.txtci

10get

30

3、 算法基本思想

先對整數分解分析能夠發現以下結論:

若 a + b = const,則 |a - b| 越小,a·b越大。

根據原問題的描述,須要將正整數n分解爲若干互不相同的天然數的和,同時又要使天然數的乘積最大。當n<4 時對n的分解的乘積是小於n的;當n大於或等於4時,n = 1 + (n-1)因子的乘積也是小於n的,因此n = a + (n-a), 2≤a≤n-2,能夠保證乘積大於n,即越分解乘積越大。

所以基於以前發現的結論和上面的分析,能夠採用以下貪心策略:將n分紅從2開始的連續天然數的和,若是最後剩下一個數,將此數在後項優先的方式下均勻地分給前面各項。

該貪心策略首先保證了正整數所分解出的因子之差的絕對值最小,即|a - b|最小;同時又能夠將其分解成儘量多的因子,且因子的值較大,確保最終所分解的天然數的乘積能夠取得最大值。

4、 算法實現(C語言)

 1 /************************************************* 
 2     File Name:  optimal_decomposition.cpp 
 3     Functions:    最優分解問題求解
 4                 將正整數n分解爲若干個天然數的和,
 5                 使這些天然數的乘積最大。
 6     Author:        Jeccey     
 7     Created:     Jeccey
 8     Last Change: 2013-07-03 
 9 **************************************************/
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 const int MAX = 51;     
16 int a[MAX - 1];        //記錄所分解的天然數        
17 
18 int PIntdecomp(int n);
19 
20 int main()
21 {
22     int n;
23     char ch;
24 
25 
26     FILE *fp1, *fp2;
27     if( (fp1=fopen("input.txt","r")) == NULL){
28         printf("cannot open file!\n");
29         exit(0);    
30     }
31     fscanf(fp1,"%d",&n);
32 
33     memset(a, 0, MAX*sizeof(int));
34 
35     if( (fp2=fopen("output.txt","w")) == NULL){
36         printf("cannot open file!\n");
37         exit(0);    
38     }
39     fprintf(fp2,"%d\n",PIntdecomp(n));
40 
41     return 0;    
42 }
43 
44 /**************************************************** 
45     Function name:    PIntedecomp 
46     Description: 將正整數n分解爲若干個天然數的和,
47                 保證所分解天然數的乘積最大並返回。 
48     Arguments:    n (int類型,且n<=437)
49 
50     Returns:    mresult, int 類型
51                 n所分解的天然數的乘積,返回0表示錯誤 
52 *****************************************************/
53 int PIntdecomp(int n)
54 {
55     int k,j,mresult;
56     
57     if (n < 1 )        //非正整數返回0 
58         return 0;    
59     if (n < 5)        //若n<5,結果是其自己 
60         return n;
61     else{            //若 n>= 5 
62         k = 0;
63         a[k] = 2;
64         n -= 2;
65         /* 貪心策略:先從2開始分紅連續天然數的和 */
66         for (; n > a[k]; ){
67             a[++k] = a[k-1] + 1;
68             n -= a[k];
69         }
70         /* 若是剩下一個數,將其按後項優先的方式
71         均勻分給前面各項 */ 
72         if (n == a[k]){
73             a[k]++;
74             n--;
75         }
76         for (j = 0; j < n; j++){
77             a[k-j]++;
78         }
79         /* 計算連乘積 */ 
80         for(mresult = 1, j = 0; j <= k; j++){
81             mresult *= a[j];
82         }
83         
84         return mresult;
85     }        
86 }
View Code

 

5、關於天然數因子可重複狀況

  n<4  ——  乘積<n

  n≥4—— 1. 1和(n-1)→乘積<n,無效;

        2. a和(n-a),且 2≤a≤n-2,分解使乘積增長(能夠證實)。

  若因子大於4則繼續分解,直至a和(n-a)都小於4。

  所以最終分解結果:全是2或3;又3×3>2×2×2,因此有三個2換成兩個3。

最終結果:「M個3」或「M個3和一個2」或「M個三和兩個2」

即 R=3^M 或 R=(3^M)×2或 R=(3^M)×4

 

 

相關文章
相關標籤/搜索