三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

俗称蓝桥杯之枚举(二)

俗称蓝桥杯之枚举(二)

一、基础枚举(单循环)

1. 反倍数 / 不能被整除的数

题目:求 1~n 中,不是 a、b、c 倍数的数有多少个。

#include <iostream> using namespace std; int main() { int n, a, b, c, cnt = 0; cin >> n >> a >> b >> c; for (int i = 1; i <= n; ++i) { if (i % a && i % b && i % c) cnt++; } cout << cnt; return 0; }

枚举要点:遍历所有数 → 判断条件 → 计数。


2. 数字统计(统计 1~n 中 2 出现次数)

题目:求 1~n 中数字2一共出现多少次。

#include <iostream> using namespace std; int main() { int n, cnt = 0; cin >> n; for (int i = 1; i <= n; ++i) { int x = i; while (x) { if (x % 10 == 2) cnt++; x /= 10; } } cout << cnt; return 0; }

枚举要点:每个数拆位判断。


二、双重 / 三重循环枚举

3. 百钱买百鸡(经典三元枚举)

题目:公鸡 5 元 1 只,母鸡 3 元 1 只,小鸡 1 元 3 只。用 100 元买 100 只鸡,求所有方案。

#include <iostream> using namespace std; int main() { for (int x = 0; x <= 20; ++x) // 公鸡 for (int y = 0; y <= 33; ++y) { // 母鸡 int z = 100 - x - y; // 小鸡 if (5*x + 3*y + z/3 == 100 && z%3 == 0) { cout << x << " " << y << " " << z << endl; } } return 0; }

枚举技巧

  • 只枚举公鸡、母鸡
  • 小鸡由总数推出,减少一层循环

4. 三位数水仙花数

题目:100~999 中,各位立方和 = 本身。

#include <iostream> using namespace std; int main() { for (int i = 100; i < 1000; ++i) { int a = i/100, b = i/10%10, c = i%10; if (a*a*a + b*b*b + c*c*c == i) cout << i << endl; } return 0; }

三、日期 / 字符串枚举(高频)

5. 回文日期(蓝桥杯最爱)

题目:求 8 位数字日期中,是回文数的日期。如 20200202 → 正反一样。

#include <iostream> #include <string> using namespace std; bool isPalin(string s) { return s == string(s.rbegin(), s.rend()); } int main() { // 枚举年份,构造回文日期 for (int y = 1000; y <= 9999; ++y) { string s = to_string(y); string mon = s.substr(3,1) + s.substr(2,1); string day = s.substr(1,1) + s.substr(0,1); string date = s + mon + day; if (isPalin(date)) { cout << date << endl; } } return 0; }

枚举技巧:只枚举年份,后半直接反转生成,速度极快


四、二进制枚举(子集枚举)

6. 子集和 / 选数

题目:n 个数,判断是否能选出若干个和为 S。(n ≤ 20)

#include <iostream> using namespace std; int a[25], n, S; int main() { cin >> n >> S; for (int i = 0; i < n; ++i) cin >> a[i]; for (int mask = 0; mask < (1 << n); ++mask) { int sum = 0; for (int i = 0; i < n; ++i) if (mask & (1 << i)) sum += a[i]; if (sum == S) { cout << "YES" << endl; return 0; } } cout << "NO"; return 0; }

适用:n ≤ 20,2²⁰ ≈ 1e6 完全没问题。


五、排列枚举(递归枚举)

7. 全排列

题目:输出 1~n 的全排列。

#include <iostream> #include <algorithm> using namespace std; int main() { int a[] = {1,2,3,4}; int n = 4; do { for (int i = 0; i < n; ++i) cout << a[i] << " "; cout << endl; } while (next_permutation(a, a+n)); return 0; }

蓝桥杯直接用next_permutation最稳。


六、枚举优化经典题

8. 最大子段和(暴力版)

题目:求一段连续子数组和最大。

#include <iostream> #include <algorithm> using namespace std; int a[1005]; int main() { int n, ans = -1e9; cin >> n; for (int i = 0; i < n; ++i) cin >> a[i]; for (int l = 0; l < n; ++l) { int sum = 0; for (int r = l; r < n; ++r) { sum += a[r]; ans = max(ans, sum); } } cout << ans; return 0; }

n ≤ 1000 暴力完全 AC。


七、枚举万能模板(直接背)

for (枚举所有可能) { if (满足题目条件) { 记录答案 / 输出 / 计数 } }

蓝桥杯不会做就枚举,小数据一定能拿分。

← 返回列表