HJ6 质数因子
质数因子_牛客题霸_牛客网
题目分析
算法的核心是质因数分解,它通过以下步骤实现:
1. 处理2的因子
- 首先,算法处理输入数
n
的2因子。因为2是最小的质数,也是唯一的偶数质数,所以首先检查n
能被2整除多少次。 - 使用一个
while
循环,只要n
能被2整除(n % 2 == 0
),就将2打印出来作为一个因子,并将n
除以2。 - 这个过程会一直继续,直到
n
不再是偶数(即不能被2整除)。
2. 处理大于2的因子
- 一旦完成了所有的2因子,
n
此时必然是一个奇数。接下来,算法通过一个for
循环,从3开始检查每一个奇数是否是n
的因子,直到达到sqrt(n)
。 - 对于每个这样的
i
(从3开始的奇数),使用一个内部while
循环检查i
是否能整除n
。如果是,就将i
打印为因子,并将n
除以i
,重复这个过程直到i
不能整除n
为止。 - 这里为什么检查到
sqrt(n)
就足够了?因为如果n
有一个因子f
大于它的平方根,那么n
必定还有一个因子小于或等于它的平方根(因为f1 * f2 = n
,如果两个因子都大于sqrt(n)
,它们的乘积将大于n
)。
3. 处理剩余的质数
- 完成上述步骤后,如果
n
大于2,则n
本身就是一个质数。因为任何合数在上述步骤中都已被分解成更小的质数因子,所以剩下的n
一定是质数。 - 最后,如果
n
大于2,直接将n
打印出来。
acm模式
#include <iostream>int main() {int n = 0;std::cin >> n;while (n % 2 == 0) {std::cout << 2 << " ";n = (n / 2);}for (int i = 3; i*i <= n; i += 2) {while (n % i == 0) {n = n / i;std::cout << i << " " ;}}if (n > 2) std::cout << n <<std::endl;return 0;
}
HJ7 取近似值
取近似值_牛客题霸_牛客网
题目分析
我们可以使用C++的标准库函数。我们会接收一个正浮点数,然后根据它的小数部分决定是向上取整还是向下取整。在C++中,可以使用floor
函数向下取整,使用ceil
函数向上取整,但这里我们要根据小数点后的值决定取整的方向。
acm模式
#include <iostream>
#include <cmath>int main() {float i = 0;std::cin >> i;float part = i - floor(i);if (part >= 0.5) std::cout << static_cast<int>(ceil(i)) << std::endl;else std::cout << static_cast<int>(floor(i)) << std::endl;return 0;
}
HJ8 合并表记录
合并表记录_牛客题霸_牛客网
题目分析
要实现这个功能,我们可以使用std::map
来自动对index进行排序,并且合并相同index的value值。std::map
是一个基于红黑树的容器,它可以保持键值对按键排序,并且每个键是唯一的。当我们尝试插入一个已经存在的键时,我们可以简单地将新的值加到已存在的值上。
#include <iostream>
#include <map>int main() {int n; // 存储键值对的个数std::cin >> n;std::map<int, int> records; // 使用map来自动排序并合并相同的indexfor(int i = 0; i < n; ++i) {int index, value;std::cin >> index >> value;records[index] += value; // 如果index已存在,value将被累加}// 遍历并输出合并后的键值对for(const auto& record : records) {std::cout << record.first << " " << record.second << std::endl;}return 0;
}
如果一定像我一样头铁也可以用unordered_map
acm模式
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>int main() {int n = 0, index = 0, value = 0;std::unordered_map<int, int> umap;// std::vector<std::pair<int, int>> vec;std::cin >> n;while (n--) {std::cin >> index >> value;umap[index] += value;}std::vector<std::pair<int, int>> vec(umap.begin(), umap.end());// vec = vec(umap.begin(), umap.end());std::sort(vec.begin(), vec.end(),[](std::pair<int, int> &a, std::pair<int, int> &b){return a.first < b.first;});for (std::pair<int, int> &i : vec) {std::cout << i.first << " " << i.second << std::endl;}return 0;}
HJ9 提取不重复的整数
提取不重复的整数_牛客题霸_牛客网
题目分析
为了实现这个需求,我们可以按以下步骤进行:
- 从输入的整数中从右向左读取每一位数字。
- 检查当前数字是否已经在新的整数中出现过,如果没有,则将其加入到新的整数中。
- 继续读取下一位,直到处理完整个输入整数。
- 返回这个新构建的不含重复数字的整数。
为了方便检查数字是否已经被加入到新整数中,我们可以使用一个std::set<int>
来存储已经处理过的数字,因为集合自动处理重复项。
acm模式
#include <iostream>
#include <set>int main() {int input;std::cin >> input;std::set<int> seenDigits;int result = 0;while (input > 0) {int digit = input % 10; // 获取最右边的数字if (seenDigits.insert(digit).second) { // 如果数字尚未出现过result = result * 10 + digit; // 将数字添加到结果中}input /= 10; // 移除已处理的最右边数字}std::cout << result << std::endl;return 0;
}
我的题解
#include <iostream>
#include <set>
#include <unordered_set>int main() {int n = 0, num = 0;// std::set<int> uset;std::unordered_set<int> uset;std::cin >> n;while(n > 0) {num = n % 10;if (uset.find(num) == uset.end()) {uset.insert(num);std::cout << num;}n = n / 10;}// for (int i : uset) {// std::cout << i;// }return 0;
}