HDU1398——Square Coins,HDU1465——不容易系列之一,HDU1492——The number of divisors(约数) about Humble Numbers

38 篇文章 0 订阅

HDU1398——Square Coins

题目描述

问题 - 1398 (hdu.edu.cn)

运行代码

#include <iostream>
#include <vector>
using namespace std;
int count(int amount) {
    vector<int> coins;
    for (int i = 1; i * i <= 289; ++i) {
        coins.push_back(i * i);
    }
    vector<int> dp(amount + 1, 0);
    dp[0] = 1;
    for (int coin : coins) {
        for (int i = coin; i <= amount; ++i) {
            dp[i] += dp[i - coin];
        }
    }
    return dp[amount];
}

int main() {
    int amount;
    while (cin >> amount && amount != 0) {
       cout << count(amount) << endl;
    }
    return 0;
}

代码思路

一、整体思路

代码的目的是计算使用特定的方形硬币集合来支付给定金额的方式数量。它通过动态规划的方法来解决这个组合计数问题。

二、具体函数分析

  1. 函数 count

    • 硬币集合生成:首先,通过循环生成所有可能的方形硬币的值,即从 11*1)到 28917*17)的平方数,并将它们存储在一个 vector<int> 类型的容器 coins 中。
    • 动态规划数组初始化:创建一个动态规划数组 dp,长度为 amount + 1,用于存储支付每个金额的组合数。初始时,将 dp[0] 设置为 1,这表示支付金额为 0 有一种方式(即不使用任何硬币)。
    • 动态规划计算组合数
      • 对于每个方形硬币的值 coin,遍历从 coin 到 amount 的金额范围。对于每个金额 i,如果已经知道支付 i - coin 的组合数,那么加上当前硬币 coin 就可以得到支付 i 的一种新组合方式。因此,将 dp[i - coin] 的值累加到 dp[i] 中。
      • 这样,通过遍历所有的硬币和金额范围,最终 dp[amount] 存储了支付给定金额 amount 的组合数。
    • 返回结果:最后,函数返回 dp[amount],即支付给定金额的组合数。
  2. 主函数 main

    • 输入处理循环:使用 while (cin >> amount && amount!= 0) 循环来读取输入的金额。只要输入的金额不为 0,就继续处理下一个输入。
    • 调用计数函数并输出结果:对于每个输入的金额,调用 count 函数来计算支付该金额的组合数,并将结果输出到控制台。

HDU1465——不容易系列之一

题目描述

Problem - 1465 (hdu.edu.cn)

Problem Description

大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了!做好“一件”事情尚且不易,若想永远成功而总从不失败,那更是难上加难了,就像花钱总是比挣钱容易的道理一样。
话虽这样说,我还是要告诉大家,要想失败到一定程度也是不容易的。比如,我高中的时候,就有一个神奇的女生,在英语考试的时候,竟然把40个单项选择题全部做错了!大家都学过概率论,应该知道出现这种情况的概率,所以至今我都觉得这是一件神奇的事情。如果套用一句经典的评语,我们可以这样总结:一个人做错一道选择题并不难,难的是全部做错,一个不对。
不幸的是,这种小概率事件又发生了,而且就在我们身边:
事情是这样的——HDU有个网名叫做8006的男性同学,结交网友无数,最近该同学玩起了浪漫,同时给n个网友每人写了一封信,这都没什么,要命的是,他竟然把所有的信都装错了信封!注意了,是全部装错哟!
现在的问题是:请大家帮可怜的8006同学计算一下,一共有多少种可能的错误方式呢?

Input:输入数据包含多个多个测试实例,每个测试实例占用一行,每行包含一个正整数n(1<n<=20),n表示8006的网友的人数。

Output:对于每行输入请输出可能的错误方式的数量,每个实例的输出占用一行。

Sample Input

2

3

Sample Output

1

2

运行代码

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector<long long> list(22, 0);
    list[2] = 1;
    list[3] = 2;
    for (int i = 4; i < 22; i++) {
        list[i] = (i - 1) * (list[i - 1] + list[i - 2]);
    }
    int n;
    while (cin >> n) {
        cout << list[n] <<endl;
    }
    return 0;
}

代码思路

一、整体思路

这段代码的目的是计算将 n 个元素全排列且每个元素都不在其原始位置(即全错位排列)的情况数。通过预先计算并存储较小规模问题的结果,利用递推关系来求解较大规模问题的答案,最后根据输入的 n 输出对应的全错位排列情况数。

二、具体分析

  1. 初始化向量vector<long long> list(22, 0); 创建了一个长度为 22 的 long long 类型的向量 list,并初始化为全零。这是为了存储不同数量元素的全错位排列情况数,由于题目中限定了输入的 n 在 1 < n <= 20 的范围内,这里创建长度为 22 是为了有一些额外的空间以防万一。

  2. 预计算较小规模问题的结果list[2] = 1; 表示当有两个元素时,全错位排列只有一种情况,即两个元素互换位置。list[3] = 2; 当有三个元素时,全错位排列有两种情况。

  3. 递推计算较大规模问题的结果

    • 对于 i 从 4 到 21(小于 22),使用递推公式 list[i] = (i - 1) * (list[i - 1] + list[i - 2]); 来计算 i 个元素的全错位排列情况数。
    • 这个递推公式的原理是:考虑第 i 个元素,它不能放在自己的位置,有 i - 1 种放法。假设第 i 个元素放在了第 k 个位置(k 不等于 i),那么现在问题分为两种情况:如果第 k 个元素放在了第 i 个位置,那么剩下的 i - 2 个元素进行全错位排列,情况数为 list[i - 2]。如果第 k 个元素没有放在第 i 个位置,那么就相当于对剩下的 i - 1 个元素进行全错位排列,情况数为 list[i - 1]
    • 所以总的情况数就是 (i - 1) * (list[i - 1] + list[i - 2])
  4. 输入处理与输出结果while (cin >> n) 循环不断读取输入的整数 n,只要输入有效就继续循环。对于每个输入的 n,输出 list[n],即 n 个元素的全错位排列情况数。

HDU1492——The number of divisors(约数) about Humble Numbers

题目描述

Problem - 1492 (hdu.edu.cn)

运行代码

#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
// 判断一个数是否为谦虚数
bool Humble(long long n) {
    long long temp = n;
    while (temp > 1) {
        if (temp % 2 == 0) {
            temp /= 2;
        }
        else if (temp % 3 == 0) {
            temp /= 3;
        }
        else if (temp % 5 == 0) {
            temp /= 5;
        }
        else if (temp % 7 == 0) {
            temp /= 7;
        }
        else {
            return false;
        }
    }
    return true;
}

// 计算一个数的因数个数,使用质因数分解法优化
int Divisors(long long n) {
    unordered_map<long long, int> primeFactors;
    for (long long i = 2; i * i <= n; ++i) {
        while (n % i == 0) {
            primeFactors[i]++;
            n /= i;
        }
    }
    if (n > 1) {
        primeFactors[n]++;
    }
    int count = 1;
    for (const auto& pair : primeFactors) {
        count *= (pair.second + 1);
    }
    return count;
}

int main() {
    long long n;
    while (cin >> n && n != 0) {
        if (Humble(n)) {
            cout << Divisors(n) << endl;
        }
        else {
            cout << "Not a humble number." << endl;
        }
    }
    return 0;
}

代码思路

一、整体思路

这段代码的目的是判断输入的数是否为 “谦虚数”(即其质因数仅为 2、3、5、7),并在确定为谦虚数后计算其因数的个数。

二、具体函数分析

  1. 函数 Humble

    • 这个函数用于判断一个数是否为谦虚数。
    • 它接收一个长整型参数 n
    • 首先,将输入的数 n 赋值给临时变量 temp,以保持原始输入不变。
    • 然后进入一个循环,只要 temp 大于 1,就不断检查 temp 是否能被 2、3、5、7 整除。
    • 如果 temp 能被 2 整除,就将 temp 除以 2;如果能被 3 整除,就除以 3;以此类推。
    • 如果 temp 不能被这四个数中的任何一个整除,说明 n 除了 2、3、5、7 之外还有其他质因数,函数返回 false
    • 如果循环结束时 temp 等于 1,说明 n 的质因数只有 2、3、5、7,函数返回 true
  2. 函数 Divisors

    • 这个函数用于计算一个数的因数个数。
    • 它首先创建一个无序映射 primeFactors,用于存储不同质因数及其出现的次数。
    • 然后从 2 开始遍历到 sqrt(n),检查 n 是否能被当前数 i 整除。如果能整除,就将 i 加入到 primeFactors 中,并不断将 n 除以 i,直到 n 不能再被 i 整除为止。
    • 遍历结束后,如果 n 大于 1,说明 n 本身就是一个质因数,将其加入到 primeFactors 中。
    • 接着,计算因数的个数。对于每个质因数 p,如果它在 n 中的次数为 k,那么这个质因数对因数个数的贡献是 k + 1(因为包含 0 次到 k 次幂的情况)。
    • 最后,将所有质因数的贡献相乘,得到 n 的因数个数。
  3. 主函数 main

    • 主函数使用一个循环来不断读取输入的数 n,直到输入为 0。
    • 对于每个输入的 n,先调用 Humble 判断是否为谦虚数。
    • 如果是谦虚数,调用 Divisors 计算因数个数并输出;如果不是谦虚数,输出相应的提示信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值