第十一届省赛B组C++真题解析(填空题)
1. 门牌制作
统计从1到2020的所有整数中,数字"2"出现的总次数。
通过遍历每个数并逐位检查是否为2,累计出现次数即可。
#include <iostream>
using namespace std;
int countDigitTwo(int n) {
int total = 0;
while (n) {
if (n % 10 == 2) total++;
n /= 10;
}
return total;
}
int main() {
int result = 0;
for (int i = 1; i <= 2020; ++i) {
result += countDigitTwo(i);
}
cout << result;
return 0;
}
答案:624
2. 既约分数
计算在1到2020范围内,有多少对整数 (a, b) 满足 gcd(a, b) == 1。
使用欧几里得算法求最大公约数,判断互质。
#include <iostream>
using namespace std;
int gcd(int a, int b) {
while (b) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
int count = 0;
for (int x = 1; x <= 2020; ++x) {
for (int y = 1; y <= 2020; ++y) {
if (gcd(x, y) == 1) {
count++;
}
}
}
cout << count;
return 0;
}
答案:2481215
3. 蛇形填数
在一个20×20的矩阵中按蛇形方式填充数字,求第20行第20列的数值。
将矩阵旋转45度后可视为一个等腰三角形,第k行第k列位于第(2×k−1)层的正中间。
第39层共有39个元素,前38层共(38×39)/2 = 741个数,第39层中间位置是第741 + 20 = 761个数。
答案:761
4. 跑步锻炼
从2000年1月3日开始,每天跑步,若为周一或每月1号则多跑1千米。统计到2020年10月1日共跑了多少千米。
使用日期模拟,注意闰年处理和有效日期校验。
#include <iostream>
using namespace std;
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool isLeap(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
bool isValid(int date) {
int y = date / 10000;
int m = (date / 100) % 100;
int d = date % 100;
if (m < 1 || m > 12) return false;
if (d < 1 || d > days[m]) return false;
if (m == 2 && d == 29 && !isLeap(y)) return false;
return true;
}
int main() {
int total = 3; // 初始已跑3千米
int weekday = 0; // 0=周一,1=周二...6=周日
for (int d = 20000103; d <= 20201001; ++d) {
if (!isValid(d)) continue;
weekday = (weekday + 1) % 7;
if (weekday == 0 || d % 100 == 1) {
total += 1;
}
total += 1;
}
cout << total;
return 0;
}
答案:8879
5. 七段数码管
七段数码管有7个灯段,每段可亮或灭。问有多少种亮灯组合能形成一个连通的整体(即所有亮灯段构成一个连通区域)。
使用并查集判断连通性:枚举所有非全灭的127种状态,对每种状态构建并查集,检查是否只有一个连通分量。
#include <iostream>
#include <vector>
using namespace std;
const int N = 7;
int parent[N];
bool connected[N][N] = {
{0,1,0,0,0,1,0},
{1,0,1,0,0,0,1},
{0,1,0,1,0,0,1},
{0,0,1,0,1,0,0},
{0,0,0,1,0,1,1},
{1,0,0,0,1,0,1},
{0,1,1,0,1,1,0}
};
int find(int x) {
return parent[x] == x ? x : (parent[x] = find(parent[x]));
}
bool isConnected() {
for (int i = 0; i < N; ++i) parent[i] = i;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
if (connected[i][j] && parent[i] != parent[j]) {
parent[find(i)] = find(j);
}
}
}
int components = 0;
for (int i = 0; i < N; ++i) {
if (connected[i][i] && parent[i] == i) components++;
}
return components == 1;
}
int main() {
int count = 0;
for (int mask = 1; mask < 128; ++mask) {
bool lights[N] = {};
int temp = mask;
for (int i = 0; i < N; ++i) {
lights[i] = temp & 1;
temp >>= 1;
}
bool valid = true;
for (int i = 0; i < N; ++i) {
if (lights[i]) {
for (int j = 0; j < N; ++j) {
if (lights[j] && connected[i][j]) {
parent[i] = find(i);
parent[j] = find(j);
}
}
}
}
if (isConnected()) count++;
}
cout << count;
return 0;
}
答案:100