HDU1398——Square Coins
题目描述
运行代码
#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;
}
代码思路
一、整体思路
代码的目的是计算使用特定的方形硬币集合来支付给定金额的方式数量。它通过动态规划的方法来解决这个组合计数问题。
二、具体函数分析
-
函数
count
:- 硬币集合生成:首先,通过循环生成所有可能的方形硬币的值,即从
1
(1*1
)到289
(17*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]
,即支付给定金额的组合数。
- 硬币集合生成:首先,通过循环生成所有可能的方形硬币的值,即从
-
主函数
main
:- 输入处理循环:使用
while (cin >> amount && amount!= 0)
循环来读取输入的金额。只要输入的金额不为0
,就继续处理下一个输入。 - 调用计数函数并输出结果:对于每个输入的金额,调用
count
函数来计算支付该金额的组合数,并将结果输出到控制台。
- 输入处理循环:使用
HDU1465——不容易系列之一
题目描述
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
输出对应的全错位排列情况数。
二、具体分析
-
初始化向量:
vector<long long> list(22, 0);
创建了一个长度为 22 的long long
类型的向量list
,并初始化为全零。这是为了存储不同数量元素的全错位排列情况数,由于题目中限定了输入的n
在1 < n <= 20
的范围内,这里创建长度为 22 是为了有一些额外的空间以防万一。 -
预计算较小规模问题的结果:
list[2] = 1;
表示当有两个元素时,全错位排列只有一种情况,即两个元素互换位置。list[3] = 2;
当有三个元素时,全错位排列有两种情况。 -
递推计算较大规模问题的结果:
- 对于
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])
。
- 对于
-
输入处理与输出结果:
while (cin >> n)
循环不断读取输入的整数n
,只要输入有效就继续循环。对于每个输入的n
,输出list[n]
,即n
个元素的全错位排列情况数。
HDU1492——The number of divisors(约数) about Humble Numbers
题目描述
运行代码
#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),并在确定为谦虚数后计算其因数的个数。
二、具体函数分析
-
函数
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
。
-
函数
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
的因数个数。
-
主函数
main
:- 主函数使用一个循环来不断读取输入的数
n
,直到输入为 0。 - 对于每个输入的
n
,先调用Humble
判断是否为谦虚数。 - 如果是谦虚数,调用
Divisors
计算因数个数并输出;如果不是谦虚数,输出相应的提示信息。
- 主函数使用一个循环来不断读取输入的数