蓝桥杯 ADV-153 算法提高 数的划分

算法提高 数的划分

时间限制:1.0s 内存限制:256.0MB


问题描述
  一个正整数可以划分为多个正整数的和,比如n=3时:
  3;1+2;1+1+1;
  共有三种划分方法。
  给出一个正整数,问有多少种划分方法。

输入格式
  一个正整数n

输出格式
  一个正整数,表示划分方案数

样例输入
3

样例输出
3

数据规模和约定
  n<=100
 

分析:先看一个例子,我们现在列出整数6的所有划分情况:

6

5 + 1

4 + 2

4 + 1 + 1

3 + 3

3 + 2 + 1

3 + 1 + 1 + 1

2 + 2 + 2

2 + 2 + 1 + 1

2 + 1 + 1 + 1 + 1

1 + 1 + 1 + 1 + 1 + 1 + 1

一共11种。

假设f(i, j)为对正整数i、拆分序列打头的数字不超过j的拆分方案数。例如f(4, 2)是指拆分4且拆分得到的序列打头的数字最多为2,即为

2 + 2

1 + 1 + 1 + 1

共2种,而不会出现如

3 + 1

这种以3为开头的情况。

所以递推关系式为

f(i, j) = \begin{cases} \sum_{k=1}^{j} f(i-k, k) & \text{ if } j \le i \\ f(i, i) & \text{ if } j > i \end{cases}

第一个式子是指将i拆分成:第一个数为k,然后递归的取拆分i - k并且打头的数不超过k

初始条件:

f(0, j) = 1

#include <stdio.h>

int main()
{
    int n;
    int f[105][105] = { 0 };

    scanf("%d", &n);

    for (int j = 1; j <= n; ++j)
        f[0][j] = 1;
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= i; ++j)
        {
            f[i][j] = 0;
            for (int k = 1; k <= j; ++k)
                f[i][j] += f[i-k][k];
        }
        for (int j = i + 1; j <= n; ++j)
            f[i][j] = f[i][i];
    }
    printf("%d", f[n][n]);

    return 0;
}
发布了298 篇原创文章 · 获赞 43 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/liulizhi1996/article/details/104211271