[蓝桥杯2020初赛]

本文提供了10道编程题目,涉及数字分析、数学逻辑、矩阵填充规律、编码表示、日期计算和字符串操作等多个方面,展示了算法在解决实际问题中的应用。每个题目都有详细的题面和解题思路,涵盖了递归、循环、最大公约数等编程技巧。
摘要由CSDN通过智能技术生成

1.门牌制作

题面:

小蓝要为一条街的住户制作门牌号。

这条街一共有2020 位住户,门牌号从1 到2020 编号。

小蓝制作门牌的方法是先制作0 到9 这几个数字字符,最后根据需要将字符粘贴到门牌上,例如门牌1017 需要依次粘贴字符1、0、1、7,即需要1 个字符0,2 个字符1,1 个字符7。

请问要制作所有的1 到2020 号门牌,总共需要多少个字符2?

题解:

从1到2020,对每一个数字单独计算,从个位开始一个一个比较

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
int  main()
{
    int ans=0;
    for (int i = 1; i <= 2020; i++)
    {
        int t = i;
        while (t)
        {
            if (t % 10 == 2)
                ans++;
            t /= 10;
        }
    }
    cout << ans;
    return 0;
}

2.既约分数

题面:

如果一个分数的分子和分母的最大公约数是1,这个分数称为既约分数。

例如4/3,2/5,8/1,1/7都是既约分数。

请问,有多少个既约分数,分子和分母都是1 到2020 之间的整数(包括1和2020)?

题解:

先让a%b,如果余数为0,返回 b,否则继续用b对a%b求余;

判断余数是否为1

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
int gcd(int a, int b) {
    if (a % b == 0)
        return b;
    else
        return gcd(b, a % b);
}
int  main()
{
    int ans=0;
    for (int i = 1; i <= 2020; i++)
    {
        for (int j = 1; j <= 2020; j++)
        {
            if (gcd(i,j)==1)
                ans++;
        }
    }
    cout << ans;
    return 0;
}

3.蛇形填数

题面:

如下图所示,小明用从1 开始的正整数“蛇形”填充无限大的矩阵。

容易看出矩阵第二行第二列中的数是5。请你计算矩阵中第20 行第20 列的数是多少?

题解:

找规律,发现每次间隔数加4

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
int  main()
{
    int ans=1,n=4;
    for (int i = 1; i < 20; i++)
    {
        ans += n;
        n += 4;
    }
    cout << ans;
    return 0;
}

4.七段码

题面:

小蓝要用七段码数码管来表示一种特殊的文字。

上图给出了七段码数码管的一个图示,数码管中一共有7 段可以发光的二极管,分别标记为a, b, c, d, e, f, g。

小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。

例如:b 发光,其他二极管不发光可以用来表达一种字符。

例如:c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。

例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。

例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光的二极管没有连成一片。

请问,小蓝可以用七段码数码管表达多少种不同的字符?

题解:

采用递归,列出所有可能的发光情况。

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
int ans;
int e[10][10], p[10], use[10];
void init()           
{
    e[1][2] = e[1][6] = 1;
    e[2][1] = e[2][7] = e[2][3] = 1;
    e[3][2] = e[3][4] = e[3][7] = 1;
    e[4][3] = e[4][5] = 1;
    e[5][4] = e[5][6] = e[5][7] = 1;
    e[6][1] = e[6][5] = e[6][7] = 1;
}
int find(int x) 
{     
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}
void dfs(int d) 
{
    if (d == 8)
    {
        for (int i = 1; i <= 7; i++)      
            p[i] = i;

        for (int i = 1; i <= 7; i++)
            for (int j = 1; j <= 7; j++)
                if (e[i][j] && use[i] && use[j])
                    p[find(i)] = find(j);      
        int k = 0;
        for (int i = 1; i <= 7; i++)
            if (use[i] && p[i] == i)
                k++;
        if (k == 1)    
            ans++;

        return;
    }
    use[d] = 1;      
    dfs(d + 1);
    use[d] = 0;      
    dfs(d + 1);
}
int main()
{
    init();
    dfs(1);
    printf("%d", ans);
}

5.跑步锻炼

题面:

小蓝每天都锻炼身体。

正常情况下,小蓝每天跑1 千米。如果某天是周一或者月初(1 日),为了激励自己,小蓝要跑2 千米。如果同时是周一或月初,小蓝也是跑2 千米。

小蓝跑步已经坚持了很长时间,从2000 年1 月1 日周六(含)到2020 年10 月1 日周四(含)。

请问这段时间小蓝总共跑步多少千米?

题解:

判断闰年,然后循环计算即可

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
int main()
{
    int week=6, ans = 0;
    int month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    for (int i = 2000; i <= 2020; i++)
    {
        if (i % 4 == 0)
            month[2] = 29;
        else
            month[2] = 28;
        for (int m = 1; m <= 12; m++)
        {
            for (int day = 1; day <= month[m]; day++)
            {
                ans++;
                if (week > 7)
                    week = 1;
                if (week == 1 || day == 1)
                    ans++;
                week++;
                if (i == 2020 && m == 10 && day == 1)
                {
                    cout << ans;
                    return 0;
                }
            }
        }
    }
}

6.回文日期

题面:

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年2 月2日。因为如果将这个日期按“yyyymmdd” 的格式写成一个8 位数是20200202,恰好是一个回文数。我们称这样的日期是回文日期。

有人表示20200202 是“千年一遇” 的特殊日子。对此小明很不认同,因为不到2 年之后就是下一个回文日期:20211202 即2021 年12 月2 日。

也有人表示20200202 并不仅仅是一个回文日期,还是一个ABABBABA型的回文日期。对此小明也不认同,因为大约100 年后就能遇到下一个ABABBABA 型的回文日期:21211212 即2121 年12 月12 日。算不上“千年一遇”,顶多算“千年两遇”。

给定一个8 位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA 型的回文日期各是哪一天。

题解:

模拟会超时

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
int month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
bool check(int date)
{
    int year = date / 10000;
    int m = date % 10000 / 100;
    int day = date % 100;
    if (!day || m < 0 || m > 12)
        return 0;
    if (m != 2 && day > month[m]) 
        return 0;
    if (m == 2)
    {
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) 
        {
            if (day > 29) return 0;
        }
        else
        {
            if (day > 28) return 0;
        }
    }
    return 1;
}
bool check1(string s)  
{
    int len = s.size();
    for (int i = 0, j = len - 1; i < j; i++, j--)  
    {
        if (s[i] != s[j])
            return 0;
    }
    return 1;
}
bool check2(string s)  
{
    if (check1(s)) 
    {
        if (s[0] != s[2] || s[1] != s[3] || s[0] == s[1])
            return 0;
        return 1;
    }
}
void solve()
{
    int date;
    bool flag = 1;
    cin >> date;
    for (int i = date+1;; i++)
    {
        string s = to_string(i);
        if (check(i))
        {
            if (check1(s) && flag)
            {
                cout << i << endl;
                flag = 0;
            }
            if (check1(s))
            {
                if (check2(s))
                {
                    cout << i << endl;
                    return;
                }
            }
        }
    }
}
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
}

7.字串排序

题面:

小蓝最近学习了一些排序算法,其中冒泡排序让他印象深刻。

在冒泡排序中,每次只能交换相邻的两个元素。

小蓝发现,如果对一个字符串中的字符排序,只允许交换相邻的两个字符,则在所有可能的排序方案中,冒泡排序的总交换次数是最少的。

例如,对于字符串lan 排序,只需要1 次交换。对于字符串qiao 排序,总共需要4 次交换。

小蓝的幸运数字是V,他想找到一个只包含小写英文字母的字符串,对这个串中的字符进行冒泡排序,正好需要V 次交换。请帮助小蓝找一个这样的字符串。

如果可能找到多个,请告诉小蓝最短的那个。

如果最短的仍然有多个,请告诉小蓝字典序最小的那个。

请注意字符串中可以包含相同的字符。

题解:

8.成绩统计

题面:

小蓝给学生们组织了一场考试,卷面总分为100 分,每个学生的得分都是一个0 到100 的整数。

如果得分至少是60 分,则称为及格。如果得分至少为85 分,则称为优秀。

请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整数。

题解:

主要处理四舍五入,先*1000再取个位,判断是否大于5,大于5就加10。

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
int she(int x)
{
    if (x % 10 > 5)
        x += 10;
     x /= 10;
     return x;
}
int main()
{
    int n,jg=0,yx=0,g,ans1,ans2;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> g;
        if (g >= 60)
            jg++;
        if (g >= 85)
            yx++;
    }
    ans1 = jg * 1000 / n;
    ans2 = yx * 1000 / n;
    ans1 = she(ans1);
    ans2 = she(ans2);
    printf("%d%%\n%d%%", ans1, ans2);
}

9.子串分值和

题面:

对于一个字符串S ,我们定义S 的分值f (S ) 为S 中出现的不同的字符个数。

例如f (”aba”) = 2, f (”abc”) = 3, f (”aaa”) = 1。

现在给定一个字符串S [0 : n - 1](长度为n),请你计算对于所有S 的非空子串S [i : j](0 ≤ i ≤ j < n), f (S [i:: j]) 的和是多少。

题解:

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
int last[200];
int main()
{
    string s;
    cin >> s;
    int n = s.size();
    s = ' ' + s;
    LL ans = 0;
    for (int i = 1; i <= n; i++)
    {
        ans += (LL)(i - last[s[i]]) * (n - i + 1);
        last[s[i]] = i;
    }
    cout << ans << endl;
    return 0;
}

10.平面切分

题面:

平面上有N 条直线,其中第i 条直线是y = Ai * x + Bi。

请计算这些直线将平面分成了几个部分。

输入格式

第一行包含一个整数N。

以下N 行,每行包含两个整数Ai, Bi。

对于50% 的评测用例,1 ≤ N ≤ 4, -10 ≤ Ai, Bi ≤ 10。

对于所有评测用例,1 ≤ N ≤ 1000, -100000 ≤ Ai, Bi ≤ 100000。

输出格式

一个整数代表答案。

题解:

#include<stdio.h>
#include<iostream>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
typedef long long LL;
long double s[1010][2];
long long ans;
bool st[1010];
pair<long double, long double> p;
int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> s[i][0] >> s[i][1];
        set<pair<long double, long double>> points;

        for (int j = 0; j < i; j++)
        {
            if (st[j])continue;
            if (s[i][0] == s[j][0]) 
            {
                if (s[i][1] == s[j][1])
                {
                    st[i] = true;
                    break;
                }
                else continue;
            }
            p.first = (s[j][1] - s[i][1]) / (s[i][0] - s[j][0]);
            p.second = s[i][0] * p.first + s[i][1];
            points.insert(p);
        }
        if (!st[i])ans += points.size() + 1;
    }
    cout << ans + 1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值