蓝桥杯备赛-2022分解成10个数(蓝桥云课题目代号:2186)

问题描述

将 2022 拆分成 10 个互不相同的正整数之和, 总共有多少种拆分方法?

注意交换顺序视为同一种方法, 例如 2022=1000+1022 和 2022=1022+1000 就视为同一种方法。

答案提交

这是一道结果填空的题, 你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。

【思路分析】

这是一道填空题,这里我们了解一下题目的要求是在1~2022这些数字中挑选10个进行组合,使得这10个数字之和为2022。这里我主要讲解以动态规划进行解决。

【题目解析】

将2022分解成10个数字之和,这些数字都是正整数。这里我们可以将分解看作是01背包的问题。

将2022看作是这个背包的容量,选取的物品是10个,每个物品的体积也就是这些数字的数值。那么,现在的问题是在1~2022这些物品中,挑选出10件物品,使得这些物品的价值总量为2022。

【解答设计】

此时我们构建出一个3维数组dp[i][j[[k],这个数字的意义是在1~i个数字中,挑选j个数字,使得这些数字的和为k。

通俗的说,就是在1到i个物品中,挑选出j个物品,使得这j个物品的总价值为k。在这个题目中,j就是10个数,k就是2022,1~i就是1~2022。我们的任务就是在这里进行选择物品并放到这个总容量为2022的背包中。那么,具体我们应该怎么选择呢?

对于数字的选择,我们分为两种情况

1.k>=i 时,(此时的总和2022大于当前的数字i,说明此时的总和还不到2022),这个数字i我们可以选择进来,也可以不选择这个数字(因为还有后面的可以选,所以这个数字不是非选择进背包不可)。

(1)选i。此时 dp[i][j][k] = dp[i-1][j-1][k-i]; 意味着选择i之前,在i-1个数字中选择了j-1个数,总和为k-i。(因为一共是选j个,除去这个i,选择了j-1个;要求的总和为k,那么在加上i之前的总和为k-i)

(2)不选i。此时dp[i][j][k] = dp[i-1][j][k]; 意味着在i-1个数字中,我们选择了j个数字,使得总和为k,因此不需要选i了。

2.k < i 时,(此时说明当前的数字比总和还大,我们当然不可以选择进来,因为背包“装不下”)

此时的dp[i][j][k] = dp[i-1][j][k];意味着在i-1个数字中,选择了j个,总和为k。

【思路总结】

综合上述的分析,代码如下:

#include <iostream>
using namespace std;

//建设3维数组dp[i][j][k],表示在前i个数字中,选取j个数字,使得总和为k的方案数
long long dp[2023][11][2023] = {0};

int main() {

    for (int i = 0; i <= 2022; i++)
    {
        dp[i][0][0] = 1;  //表示在前i个数字,选取0个数字,总和为0的方案数为1,唯一的方案
    }

    for (int i = 1; i <= 2022; i++)
    {
        for (int j = 1; j <= 10; j++)
        {
            for (int k = 1; k <= 2022; k++)
            {
                if (k >= i)
                {
                    dp[i][j][k] = dp[i-1][j-1][k-i] + dp[i-1][j][k];
                }
                else
                {
                    dp[i][j][k] = dp[i-1][j][k];
                }
            }
        }
    }
    cout << dp[2022][10][2022] << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值