åŸºæœ¬æ•´æ•°åˆ’åˆ†é—®é¢˜æ˜¯å°†ä¸€ä¸ªæ£æ•´æ•°n拆æˆä¸€ç»„æ•°è¿žåŠ å¹¶ç‰äºŽn的形å¼ï¼Œä¸”这组数ä¸çš„æœ€å¤§åŠ æ•°ä¸å¤§äºŽm。
å³n=n1+n2+n3+……
(其ä¸ï¼Œn1>=n2>=n3>=n4……)
对于这ç§é—®é¢˜ï¼Œå¯ä»¥å»ºç«‹ä¸€ä¸‹é€’归关系:
(1)q(n,1)=1,n>=1;
å½“æœ€å¤§åŠ æ•°mä¸å¤§äºŽ1æ—¶ï¼Œä»»ä½•æ£æ•´æ•°nåªæœ‰ä¸€ç§åˆ’分,å³n=1+1+1+1+1……
(2)q(n,m)=q(n,n),m>=n;
å› ä¸ºï¼Œæ˜¾ç„¶æœ€å¤§åŠ æ•°ä¸èƒ½å¤§äºŽn……,囧
(3)q(n,n)=q(n,n-1)+1;
æ£æ•´æ•°n的划分由n=nå’Œm<=n-1的划分组æˆ
(å³å¦‚æžœåˆ’åˆ†ä¸æœ€å¤§åŠ æ•°æ˜¯n,则这ç§åˆ’分为n=nï¼Œå‰©ä¸‹çš„åˆ’åˆ†æœ€å¤§åŠ æ•°ä¸ºn-1)
(4)q(n,m)=q(n,m-1)+q(n-m,m);
åŒä¸Šï¼Œæ£æ•´æ•°n的划分由m=må’Œm<=m-1的划分组æˆ(å³å¦‚æžœåˆ’åˆ†ä¸æœ€å¤§åŠ æ•°æ˜¯m,
则这ç§åˆ’分为n-m(将划分ä¸çš„一个必然å˜åœ¨çš„må‡åŽ»ï¼‰çš„æœ€å¤§åŠ æ•°ä¸ºm的划分,
å‰©ä¸‹çš„ä¸ºæœ€å¤§åŠ æ•°ä¸ºm-1的划分)
ç”±æ¤å¯è®¾è®¡é€’归函数如下(C++)
#include <stdio.h>
int numdipart(int n,int m)
//æ±‚å¯¹äºŽæ£æ•´æ•°nï¼Œå…¶æœ€å¤§åŠ æ•°ä¸å¤§äºŽm的划分个数,算法效
//率低(递归),当n超过80时,
//è¿ç®—时间超过一秒,对于m==n的问题建议打表
{
if(n<1 || m<1) return 0;
if(n==1 || m==1) return 1;
if(n<m) return numdipart(n,n);
if(n==m) return numdipart(n,m-1)+1;
return numdipart(n,m-1)+numdipart(n-m,m);
}
ç”±äºŽé€’å½’ç®—æ³•æ•ˆçŽ‡å¾ˆä½Žï¼ŒåŒæ—¶ç”±äºŽæ•´æ•°åˆ’分的整数级增长速度,故对于一般问题,完全å¯ä»¥é€šè¿‡DP打表æ¥è§£å†³ï¼Œç¨‹åºå¦‚下:
Long long dap[1001][1001];
//注æ„为long long类型,注æ„输出,之所以用long long
//ç±»åž‹æ˜¯å› ä¸ºå½“n大于300时,dap[n][n]便超出了int的范围
void dpdipart()
{
int i,j;
for(i=1;i<1001;++i)
for(j=1;j<1001;++j)
{
if(i<1 || j<1) dap[i][j]=0;
else if(i==1 || j==1) dap[i][j]=1;
else if(i<j) dap[i][j]=dap[i][i];
else if(i==j) dap[i][j]=dap[i][j-1]+1;
else dap[i][j]=dap[i][j-1]+dap[i-j][j];
}
}
如15å¯ä»¥åˆ’分æˆ4ç§è¿žç»æ•´æ•°ç›¸åŠ çš„å½¢å¼ï¼š
15
7 8
4 5 6
1 2 3 4 5
首先考虑一般的形å¼ï¼Œè®¾nä¸ºè¢«åˆ’åˆ†çš„æ£æ•´æ•°ï¼Œxä¸ºåˆ’åˆ†åŽæœ€å°çš„æ•´æ•°ï¼Œå¦‚æžœn有一ç§åˆ’分,那么
结果就是x,如果有两ç§åˆ’分,就是xå’Œx x + 1
, 如果有mç§åˆ’分,就是 x ã€x x + 1 〠x x + 1 x + 2 ã€... ã€x x + 1 x + 2 ... x + m - 1
å°†æ¯ä¸€ä¸ªç»“æžœç›¸åŠ å¾—åˆ°ä¸€ä¸ªå…¬å¼(i * x + i * (i - 1) / 2) = n
,i
为当å‰åˆ’分åŽç›¸åŠ çš„æ£æ•´æ•°ä¸ªæ•°ã€‚
满足æ¡ä»¶çš„划分就是使xä¸ºæ£æ•´æ•°çš„æ‰€æœ‰æƒ…况。
如上例,当i = 1
时,å³åˆ’分æˆä¸€ä¸ªæ£æ•´æ•°æ—¶ï¼Œx = 15
, 当i = 2
时, x = 7
。
当i = 3
时,x = 4
, 当i = 4
时,9/4ï¼Œä¸æ˜¯æ£æ•´æ•°ï¼Œå› æ¤ï¼Œ15ä¸å¯èƒ½åˆ’分æˆ4ä¸ªæ£æ•´æ•°ç›¸åŠ ã€‚
当i = 5
时,x = 1
。
这里还有一个问题,这个i的最大值是多少?ä¸è¿‡æœ‰ä¸€ç‚¹å¯ä»¥è‚¯å®šï¼Œå®ƒä¸€å®šæ¯”nå°ã€‚我们å¯ä»¥åšä¸€ä¸ªå‡è®¾ï¼Œ
å‡è®¾nå¯ä»¥æ‹†æˆæœ€å°å€¼ä¸º1的划分,如上例ä¸çš„1 2 3 4 5。这是nçš„æœ€å¤§æ•°ç›®çš„åˆ’åˆ†ã€‚å¦‚æžœä¸æ»¡è¶³è¿™ä¸ªå‡è®¾ï¼Œé‚£ä¹ˆ i 一定比这个划分ä¸çš„æ£æ•´æ•°ä¸ªæ•°å°ã€‚å› æ¤å¯ä»¥å¾—åˆ°è¿™æ ·ä¸€ä¸ªå…¬å¼i * (i + 1) / 2 <= n
,å³å½“iæ»¡è¶³è¿™ä¸ªå…¬å¼æ—¶næ‰å¯èƒ½è¢«åˆ’分。
综上所诉,å¯å¾—程åºå¦‚下:
int split(int n)
//æ¤ç¨‹åºç”¨mè®°å½•åˆ’åˆ†ç§æ•°å¹¶è¿”回m值,并且在函数体内输出了å„ç§åˆ’分
//ç§ç±»ï¼Œn在int范围内皆å¯å¤„ç†ï¼Œå¤„ç†æ—¶é—´å°äºŽ1ç§’
{
int i, j, m = 0, x, t;
for(i = 1;(i*(i+1)/2)<=n; i++)
{
t = n - i*(i-1)/2;
x = t / i;
if(x <= 0) break;
if(t % i == 0)
{
printf("%d ", x);
for(j = 1; j < i; j++)
printf("%d ", x + j);
printf("\n");
m++;
}
}
return m;
}
递归æœç´¢æ¯ä¸€ä¸ªå¯èƒ½çš„å› å,当æœç´¢åˆ°åº•部(为1æ—¶ï¼‰ï¼Œå› å分解方å¼åŠ 1ï¼Œæ¤æ—¶ä¹Ÿå¯è¿›è¡Œè¾“出
void solve(int n)
{
int i;
if(n==1) sum++;
else
for(i=2;i<=n;++i)
if(n%i==0)
solve(n/i);
}