文章目录
- [2025-8-11-C++ 学习 暴力枚举(2)](#2025-8-11-C++ 学习 暴力枚举(2))
- [P1036 [NOIP 2002 普及组] 选数](#P1036 [NOIP 2002 普及组] 选数)
- [P1157 组合的输出](#P1157 组合的输出)
- [P1706 全排列问题](#P1706 全排列问题)
2025-8-11-C++ 学习 暴力枚举(2)
暴力枚举,continue。
P1036 [NOIP 2002 普及组] 选数
题目描述
已知 n n n 个整数 x 1 , x 2 , ⋯ , x n x_1,x_2,\cdots,x_n x1,x2,⋯,xn,以及 1 1 1 个整数 k k k( k < n k<n k<n)。从 n n n 个整数中任选 k k k 个整数相加,可分别得到一系列的和。例如当 n = 4 n=4 n=4, k = 3 k=3 k=3, 4 4 4 个整数分别为 3 , 7 , 12 , 19 3,7,12,19 3,7,12,19 时,可得全部的组合与它们的和为:
3 + 7 + 12 = 22 3+7+12=22 3+7+12=22
3 + 7 + 19 = 29 3+7+19=29 3+7+19=29
7 + 12 + 19 = 38 7+12+19=38 7+12+19=38
3 + 12 + 19 = 34 3+12+19=34 3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数: 3 + 7 + 19 = 29 3+7+19=29 3+7+19=29。
输入格式
第一行两个空格隔开的整数 n , k n,k n,k( 1 ≤ n ≤ 20 1 \le n \le 20 1≤n≤20, k < n k<n k<n)。
第二行 n n n 个整数,分别为 x 1 , x 2 , ⋯ , x n x_1,x_2,\cdots,x_n x1,x2,⋯,xn( 1 ≤ x i ≤ 5 × 10 6 1 \le x_i \le 5\times 10^6 1≤xi≤5×106)。
输出格式
输出一个整数,表示种类数。
输入输出样例 #1
输入 #1
4 3
3 7 12 19
输出 #1
1
说明/提示
【题目来源】
NOIP 2002 普及组第二题
提交代码
cpp
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// 判断一个数是否为素数
bool isPrime(int num) {
if (num < 2) return false;
if (num == 2) return true;
if (num % 2 == 0) return false;
for (int i = 3; i <= sqrt(num); i += 2) {
if (num % i == 0) return false;
}
return true;
}
// 递归生成组合并计算符合条件的数量
void countCombinations(const vector<int>& nums, int index, int k, int currentSum, int selected, int& result) {
// 如果已经选了k个数,判断和是否为素数
if (selected == k) {
if (isPrime(currentSum)) {
result++;
}
return;
}
// 如果剩余元素不够选,直接返回
if (index + (k - selected) > nums.size()) {
return;
}
// 不选当前元素
countCombinations(nums, index + 1, k, currentSum, selected, result);
// 选当前元素
countCombinations(nums, index + 1, k, currentSum + nums[index], selected + 1, result);
}
int main() {
int n, k;
cin >> n >> k;
vector<int> nums(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
int result = 0;
countCombinations(nums, 0, k, 0, 0, result);
cout << result << endl;
return 0;
}
P1157 组合的输出
题目描述
排列与组合是常用的数学方法,其中组合就是从 n n n 个元素中抽出 r r r 个元素(不分顺序且 r ≤ n r \le n r≤n),我们可以简单地将 n n n 个元素理解为自然数 1 , 2 , ... , n 1,2,\dots,n 1,2,...,n,从中任取 r r r 个数。
现要求你输出所有组合。
例如 n = 5 , r = 3 n=5,r=3 n=5,r=3,所有组合为:
123 , 124 , 125 , 134 , 135 , 145 , 234 , 235 , 245 , 345 123,124,125,134,135,145,234,235,245,345 123,124,125,134,135,145,234,235,245,345。
输入格式
一行两个自然数 n , r ( 1 < n < 21 , 0 ≤ r ≤ n ) n,r(1<n<21,0 \le r \le n) n,r(1<n<21,0≤r≤n)。
输出格式
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。
注意哦!输出时,每个数字需要 3 3 3 个场宽。以 C++ 为例,你可以使用下列代码:
cpp
cout << setw(3) << x;
输出占 3 3 3 个场宽的数 x x x。注意你需要头文件 iomanip
。
输入输出样例 #1
输入 #1
5 3
输出 #1
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
提交代码
cpp
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
// 递归生成组合
void generateCombinations(int n, int r, int start, vector<int>& current) {
// 如果当前组合的大小达到r,输出该组合
if (current.size() == r) {
for (int num : current) {
// 每个数字占3个字符宽度
cout << setw(3) << num;
}
cout << endl;
return;
}
// 从start开始选择下一个数字,确保组合递增且不重复
for (int i = start; i <= n; ++i) {
current.push_back(i);
// 下一个数字要比当前数字大,保证组合递增
generateCombinations(n, r, i + 1, current);
current.pop_back(); // 回溯
}
}
int main() {
int n, r;
cin >> n >> r;
// 特殊情况处理:当r=0时,没有组合需要输出
if (r == 0) {
return 0;
}
vector<int> current;
generateCombinations(n, r, 1, current);
return 0;
}
P1706 全排列问题
题目描述
按照字典序输出自然数 1 1 1 到 n n n 所有不重复的排列,即 n n n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式
一个整数 n n n。
输出格式
由 1 ∼ n 1 \sim n 1∼n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5 5 5 个场宽。
输入输出样例 #1
输入 #1
3
输出 #1
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
说明/提示
1 ≤ n ≤ 9 1 \leq n \leq 9 1≤n≤9。
提交代码
cpp
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;
// 递归生成全排列
void generatePermutations(int n, vector<int>& current, vector<bool>& used) {
// 如果当前排列长度等于n,输出该排列
if (current.size() == n) {
for (int num : current) {
// 每个数字占5个字符宽度
cout << setw(5) << num;
}
cout << endl;
return;
}
// 尝试添加每个未使用过的数字
for (int i = 1; i <= n; ++i) {
if (!used[i]) {
used[i] = true; // 标记为已使用
current.push_back(i); // 添加到当前排列
generatePermutations(n, current, used); // 递归生成后续排列
current.pop_back(); // 回溯:移除最后一个数字
used[i] = false; // 回溯:标记为未使用
}
}
}
int main() {
int n;
cin >> n;
vector<int> current; // 存储当前排列
vector<bool> used(n + 1, false); // 标记数字是否已使用
generatePermutations(n, current, used);
return 0;
}