第十一届蓝桥杯大赛软件类省赛第二场 C/C++ 大学 B 组

试题A.门牌制作
小蓝要为一条街的住户制作门牌号。
这条街一共有 2020 位住户,门牌号从 1 到 2020 编号。
小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字
符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、0、1、7,即需要 1 个
字符 0,2 个字符 1,1 个字符 7。
请问要制作所有的 1 到 2020 号门牌,总共需要多少个字符 2?

答案:624

代码如下:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int res = 0;
    for (int i = 1; i <= 2020; i++)
    {
        int j = i;
        while (j)
        {
            if (j % 10 == 2)
                res++;
            j /= 10;
        }
    }
    cout << res << endl;
    return 0;
}
试题B.既约分数
如果一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数。
例如,34 , 52 , 18 , 71 都是既约分数。
请问,有多少个既约分数,分子和分母都是 1 到 2020 之间的整数(包括 1 和 2020)?

答案:2481215

代码如下:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int res = 0;
    for (int i = 1; i <= 2020; i++)
    {
        for (int j = 1; j <= 2020; j++)
        {
            if (__gcd(i, j) == 1)
                res++;
        }
    }
    cout << res << endl;
    return 0;
}
试题C.蛇形填数
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
1 2 6 7 15 ...
3 5 8 14 ...
4 9 13 ...
10 12 ...
11 ...
...
(1)
容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列
的数是多少?

答案:761

代码如下:

#include <bits/stdc++.h>
using namespace std;

int mp[50][50], ct;
int main()
{
    for (int i = 1; i <= 40; i++)
        if (i & 1)
        {
            int nowi = i, nowj = 1;
            for (int j = 0; j < i; j++)
                mp[nowi - j][nowj + j] = ++ct;
        }
        else
        {
            int nowi = 1, nowj = i;
            for (int j = 0; j < i; j++)
                mp[nowi + j][nowj - j] = ++ct;
        }
    // for (int i = 1; i <= 20; i++)
    // {
    //     for (int j = 1; j <= 20; j++)
    //         cout << mp[i][j] << ' ';
    //     cout << endl;
    // }
    cout << mp[20][20] << endl;
    return 0;
}
试题D.跑步锻炼
小蓝每天都锻炼身体。
正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1 日),为了
激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年
10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?

答案:8879

代码如下:


#include <bits/stdc++.h>
using namespace std;

int MONTH[13] = {0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int f(int year)
{
    if (year % 400 == 0 || (year % 4 == 0 && year % 100))
        MONTH[2] = 29;
    else
        MONTH[2] = 28;
}
int main()
{
    int y = 2000, m = 1, d = 1, wek = 6, ans = 2; //ans初始值为2 (第一天跑2KM
    while (y != 2020 || m != 10 || d != 1)
    {
        f(y);
        d++;
        wek = (wek + 1) % 7;
        if (d > MONTH[m])
        {
            d = 1;
            m++;
            if (m > 12)
            {
                m = 1;
                y++;
            }
        }
        if (d == 1 || wek == 1)
            ans += 2;
        else
            ans += 1;
    }
    cout << ans << endl;
    return 0;
}
试题E.七段码
小蓝要用七段码数码管来表示一种特殊的文字。
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二
极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符
的表达时,要求所有发光的二极管是连成一片的。
例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上
一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光
的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?

思路:把 a b c d e f g abcdefg abcdefg按成 1234567 1234567 1234567,建图跑 D F S DFS DFS

答案:80

代码如下:

#include <bits/stdc++.h>
using namespace std;

int head[100];
int ct = 1;
struct node
{
    int v, next;
} e[100];

void add(int u, int v)
{
    e[ct].v = v;
    e[ct].next = head[u];
    head[u] = ct++;
    swap(u, v);
    e[ct].v = v;
    e[ct].next = head[u];
    head[u] = ct++;
}

void init() //建图
{
    add(1, 2), add(1, 6), add(2, 7), add(2, 3), add(3, 4);
    add(3, 7), add(4, 5), add(5, 6), add(5, 7), add(6, 7);
}

int ans[100], vis[100];
set<int> st;

void save(int ct)
{
    int anss[10];
    for (int i = 1; i <= ct; i++)
        anss[i] = ans[i];
    sort(anss + 1, anss + 1 + ct);
    int res = 0;
    for (int i = 1; i <= ct; i++)
        res = res * 10 + anss[i];
    st.insert(res);
}
void dfs(int now, int all, int ct)
{
    ans[ct] = now;
    if (all == ct) //如果找到了大小为all的连通块 保存答案
    {
        save(all);
        return;
    }
    for (int i = head[now]; i; i = e[i].next)
    {
        int v = e[i].v;
        if (!vis[v])
        {
            vis[v] = 1;
            dfs(v, all, ct + 1);
            vis[v] = 0;
        }
    }
}
int main()
{
    init();
    for (int i = 1; i <= 7; i++)     //起点
        for (int j = 1; j <= 7; j++) //连通块大小
        {
            vis[i] = 1;
            dfs(i, j, 1);
            vis[i] = 0;
        }
    cout << st.size() << endl;
    return 0;
}
试题F.成绩统计
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是
一个 0 到 100 的整数。
如果得分至少是 60 分,则称为及格。如果得分至少为 85 分,则称为优秀。
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整
数。

代码如下:

#include <bits/stdc++.h>
using namespace std;

int a[10010];
int main()
{
    int n, s1 = 0, s2 = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        int temp;
        scanf("%d", &temp);
        if (temp >= 60)
            s1++;
        if (temp >= 85)
            s2++;
    }
    double ans1 = (double)s1 / (double)n;
    double ans2 = (double)s2 / (double)n;
    int res1 = int(ans1 * 1000 + 5) / 10;
    int res2 = int(ans2 * 1000 + 5) / 10;
    printf("%d%%\n%d%%\n", res1, res2);
    return 0;
}
试题 G: 回文日期

可以只枚举年份,判断日期合法性,时间更快,不过暴力跑问题应该也不大

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2
日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,
恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为
不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA
型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个
ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千
年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个
ABABBABA 型的回文日期各是哪一天。

代码如下:

#include <bits/stdc++.h>
using namespace std;

int MONTH[13] = {0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int f(int year)
{
    if (year % 400 == 0 || (year % 4 == 0 && year % 100))
        MONTH[2] = 29;
    else
        MONTH[2] = 28;
}
char s[10];
bool check1(int y, int m, int d)
{
    char s1[10];
    s1[0] = y / 1000 % 10 + '0';
    s1[1] = y / 100 % 10 + '0';
    s1[2] = y / 10 % 10 + '0';
    s1[3] = y / 1 % 10 + '0';
    s1[4] = m / 10 % 10 + '0';
    s1[5] = m / 1 % 10 + '0';
    s1[6] = d / 10 % 10 + '0';
    s1[7] = d / 1 % 10 + '0';
    if (s1[0] == s1[7] && s1[1] == s1[6] && s1[2] == s1[5] && s1[3] == s1[4])
        return 1;
    return 0;
}
bool check2(int y, int m, int d)
{
    char s1[10];
    s1[0] = y / 1000 % 10 + '0';
    s1[1] = y / 100 % 10 + '0';
    s1[2] = y / 10 % 10 + '0';
    s1[3] = y / 1 % 10 + '0';
    s1[4] = m / 10 % 10 + '0';
    s1[5] = m / 1 % 10 + '0';
    s1[6] = d / 10 % 10 + '0';
    s1[7] = d / 1 % 10 + '0';
    if (s1[0] == s1[2] && s1[2] == s1[5] && s1[5] == s1[7] && s1[0] != s1[1] && s1[1] == s1[3] && s1[3] == s1[4] && s1[4] == s1[6])
        return 1;
    return 0;
}
int main()
{
    scanf("%s", s);
    int y, m, d;
    y = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
    m = (s[4] - '0') * 10 + s[5] - '0';
    d = (s[6] - '0') * 10 + s[7] - '0';
    int f1 = 0, f2 = 0;

    while (!f1 || !f2)
    {
        f(y);
        d++;
        if (d > MONTH[m])
        {
            d = 1;
            m++;
            if (m > 12)
            {
                m = 1;
                y++;
            }
        }
        if (check1(y, m, d) && !f1)
        {
            f1 = 1;
            printf("%04d%02d%02d\n", y, m, d);
        }
        if (check2(y, m, d) && !f2)
        {
            f2 = 1;
            printf("%04d%02d%02d\n", y, m, d);
        }
    }
    return 0;
}

剩下三题都不会,只能骗一部分分(还是太菜了

评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值