【两种方法】多位数的数字和问题

        今天小孩参加一个“新初一”数学思维挑战赛活动, 反馈的一道难题,为了得到答案,于是想到用C++编程来计算,题意大至如下:       

题意:

        一个数字和为10的多位数(至少三位),数字取自1、2、5、6,且数字可以不全用,也可以重复用。那么这样的多位数共有多少个?

思路1:动态规划DP

        1)定义一个数组 dp[i][j],其中 i 表示当前考虑的位数(从最低位开始,至少为3),j 表示当前已选择的数字之和。

        2)初始化 dp[1][k](其中 k 为1, 2, 5, 6)为1,表示只有一位数时,有1个数字的和为 k

        3)对于 i > 1 的情况,我们可以从 dp[i-1][j-k] 转移过来,其中 k 为当前可以选择的数字(1, 2, 5, 6),且 j-k 非负。即,如果我们在前 i-1 位得到了和为 j-k 的多位数,那么我们可以在最后一位加上数字 k,从而得到和为 j 的 i 位数。

        4)最后,我们需要的答案就是 dp[3][10] + dp[4][10] + dp[5][10] + ...,即从3位数开始,所有和为10的多位数的数量之和。

源代码:

#include <iostream>
using namespace std;
int main() {
    //初始化dp[i][j]数组,i表示当前考虑的位数,j表示当前已选择的数字之和
    int dp[11][11]={};
    // 初始化一位数的情况
    dp[1][1] = dp[1][2] = dp[1][5] = dp[1][6] = 1;
    // 动态规划过程,从第2位开始计算
    for (int i = 2; i <= 10; ++i) {  // 最多考虑10位数
        for (int j = 1; j <= 10; ++j) {  // 数字和的范围
            for (int k : {1, 2, 5, 6}) {  // 可以选择的数字
                if (j >= k)   // 保证j-k非负
                    dp[i][j] += dp[i-1][j-k];
            }
        }
    }
    // 计算结果,从3位数开始累加和为10的数的数量
    int result = 0;
    for (int i = 3; i <= 10; ++i) { 
        result += dp[i][10];
    }
    cout << "这样的多位数共有 " << result << " 个。" << endl;
    return 0;
}

思路2:递归法

  • 递归函数countNumbers,接受当前累加的和currentSum、当前数字的位数length、已经构建的数字的前缀prefix以及可用的数字集合digits

  • 函数首先检查是否达到了终止条件:如果当前和等于10且位数至少为3,则找到了一个解,并返回1。如果当前和超过10或位数超过了10位数,则函数返回0,表示不再继续搜索。

  • 在函数主体中,遍历所有可用的数字,并尝试将它们添加到当前前缀中。对于每个数字,递归调用countNumbers函数,并更新currentSumlength。递归调用返回的结果累加到count变量中。

  • 最后,输出总的数量。

源代码:

#include <iostream>
#include <vector>
using namespace std;
// 递归函数,用于计算数字和为10的多位数的数量,currentSum: 当前累加的和
// length: 当前数字的位数,prefix: 已经构建的数字的前缀(作为字符串处理)
int countNumbers(int currentSum, int length, const string& prefix, const vector<int>& digits) {
    // 终止条件:如果当前和等于10且长度至少为3,则找到一个解
    if (currentSum == 10 && length >= 3) {
        return 1; // 增加一个解
    }
    // 终止条件:如果当前和已经超过10,或者长度超过10位
    if (currentSum > 10 || length > 10) { 
        return 0; // 不再增加解
    }
    int count = 0;
    // 遍历所有可能的数字
    for (int digit : digits) {
        // 尝试添加当前数字到前缀中,并递归调用函数
        string newPrefix = prefix + to_string(digit);
        count += countNumbers(currentSum + digit, length + 1, newPrefix, digits);
    }
    return count;
}
int main() {
    vector<int> digits = {1, 2, 5, 6}; // 可用的数字
    int totalCount = countNumbers(0, 0, "", digits); // 从0开始
    cout << "这样的多位数共有 " << totalCount << " 个。" << endl;
    return 0;
}

运行结果:

这样的多位数共有 147 个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值