Combinatorics——HDUOJ 1028 - Ignatius and the Princess III (整数拆分【多种方法】)

原题


  • Problem Description

“Well, it seems the first problem is too easy. I will let you know how foolish you are later.” feng5166 says.
“The second problem is, given an positive integer N, we define an equation like this:
N=a[1]+a[2]+a[3]+…+a[m];
a[i]>0,1<=m<=N;
My question is how many different equations you can find for a given N.
For example, assume N is 4, we can find:
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
so the result is 5 when N is 4. Note that “4 = 3 + 1” and “4 = 1 + 3” is the same in this problem. Now, you do it!”

  • Input

The input contains several test cases. Each test case contains a positive integer N(1<=N<=120) which is mentioned above. The input is terminated by the end of file.

  • Output

    For each test case, you have to output a line contains an integer P which indicate the different equations you have found.

  • Sample Input

    4
    10
    20

  • Sample Output

    5
    42
    627


  • 母函数:
    #include <stdio.h>
    int Record[121];
    int c1[121], c2[121];
    int GeneratingFunction(short m)
    {
        short i, j, k;
        for (i = 0; i <= m; i++)
        {
            c1[i] = 1;
            c2[i] = 0;
        }
        for (i = 1; i <= m; i++)//i为每一个括号最开始的X的指数的值【从1开始】(1+x^i+x^2i+x^3i+......)
        {
            for (j = 0; j <= m; j++)//(x^j) = (1+x^1+x^2+x^3+......)【前一个括号所有项的指数】
                for (k = 0; k + j <= m; k += i + 1)//【后一个括号】
                    c2[k + j] += c1[j];
            for (j = 0; j <= m; j++)
            {
                c1[j] = c2[j];
                c2[j] = 0;
            }
        }
        return c1[m];
    }
    int main()
    {
        short i, N;
        for (i = 1; i <= 120; i++)
            Record[i] = GeneratingFunction(i);
        while (scanf("%d", &N) != EOF)
            printf("%d\n", Record[N]);
    }

    动态规划【非递归】 – (对于整数拆分,可求出可拆分的结果的数量)
    寻找规律,动态规划,通过数组保存(计算从小到大,大可用小),减少计算开销
    规律可参考:http://blog.csdn.net/qq_33266889/article/details/52166293

    #include <stdio.h>
    int Record[121][121];
    void CreateTable()
    {
        short n, m;
        for (n = 1; n <= 120; n++)
        {
            for (m = 1; m <= 120; m++)
            {
                if (m == 1) {
                    Record[n][m] = 1;continue;;
                }
                if (m == n) {
                    Record[n][m] = Record[n][m - 1] + 1;continue;;
                }
                if (m > n)Record[n][m] = Record[n][n];
                else Record[n][m] = Record[n][m - 1] + Record[n - m][m];
            }
        }
    }
    int main()
    {
        short N;
        CreateTable();
        while (scanf("%d",&N)!=EOF)
            printf("%d\n", Record[N][N]);
    }

    dfs深度优先搜索【递归】–(对于整数拆分,可以把拆分出来的每一个结果都一一输出)
    无规律,一一列举

    #include<stdio.h>
    int stack[121];
    int top;
    int total, n;
    int sum;
    void dfs(int index)
    {
        int i;
        if (total == n)
        {
            printf("%d=", n);
            for (i = 0;i<top - 1;i++)
                printf("%d+", stack[i]);
            printf("%d\n", stack[top - 1]);
            sum++;
        }
        if (total > n)
            return;
    
        if (total < n) 
        {
            for (i = index;i >= 1;i--)
            {
                total += i;
                stack[top++] = i;
                dfs(i);
                total -= i;
                stack[--top];
            }
        }
    }
    void main()
    {
        while (scanf("%d", &n) != EOF)
        {
            sum = top = total = 0;
            dfs(n - 1);//n-1则不包括该数本身,例如10=10
            printf("%d\n", sum);
        }
    }

    另外还有五边形数定理,可参考此文:http://blog.csdn.net/u011889952/article/details/44813593

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值