//目录

整数N分解,搭积木,离散数学中的母函数,ZOJ(1163)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1163

解题报告:

将整数N分解为:两个及以上的不重复的整数,最流行的解法是动态规划,和生成函数(01背包思路)。

 

将问题看成经典的搭积木的问题。相当与求:将N块积木搭成J排.

f[i,j] = f[i,j-1]+ f[i-j,j-1];

初始化f[0,0] = 1;

即求f[N,N] - 1;(两个及以上的)

#include <stdio.h>
#include <algorithm>
#include <string.h>
#define MAX 505

using namespace std;

long long dp[MAX][MAX];

int main()
{
    /*memset(dp,0,sizeof(dp));
    dp[0] = 1;
    for(int i=1; i<MAX; i++)
        for(int j=MAX-1; j>=i; j--)
            dp[j] += dp[j-i];*/

    int n;
    dp[0][0]=1;

    for(int i=0; i<MAX; i++)
    {
        for(int j=1; j<=i; j++)
            dp[i][j]=dp[i][j-1]+dp[i-j][j-1];

        for(int j=i+1; j<MAX; j++)
            dp[i][j]=dp[i][i];
    }

    while(scanf("%d",&n),n)
        printf("%lld\n",dp[n][n]-1);

    return 0;
}

 

 

生成函数算法,这里的知识是离散数学中的母函数。

G(X) = (1+X)(1+X^2)(1+X^3)***(1+X^N);

这里可以看出x^3的系数为 X*X^2, 和X^3,因为这里的拆数是拆成两个及以上,所以减去X^3,及要减1;

f[j]表示x^j的系数,那么计算x^j的系数,是要累加的,这里采用01背包,f[j] += f[j-i];(i=1~0(j=i))

 

memset(dp,0,sizeof(dp));
dp[0] = 1;
for(int i=1; i<MAX; i++)
    for(int j=MAX-1; j>=i; j--)
        dp[j] += dp[j-i];
printf("%d\n",dp[n]-1);

 

posted @ 2016-05-27 19:59  小草的大树梦  阅读(471)  评论(0)    收藏  举报