第十四届蓝桥杯软件类第三场模拟赛题目解析

1.字母数

题目描述

请找到一个大于 \(2022\) 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 \(0\) )都为字母( \(A\)\(F\) )。请将这个数的十进制形式作为答案提交。

解题思路

进制转换题,从\(2022\)开始暴力,第一个数字即为正确答案。

十六进制数如下:

\(0,1,2,3,4,5,6,7,8,9,\)
\(10\ (A\ or\ a),11\ (B\ or\ b),12\ (C\ or\ c),13\ (D\ or\ d),14\ (E\ or\ e),15\ (F\ or\ f)\)

也就是说,一个十进制数要想转换成十六进制数后所有的数位都为字母的话,也就是这十进制数每次除以十六的余数均是大于十的数,即:

x mod  16 >=10

代码实现

C++实现

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

bool check(int x)
{
    while (x)
        if (x % 16 <= 9)
            return false;
        else
            x /= 16;
    return true;
}

int main()
{
    int x = 2022;
    while (true)
    {
        if (check(x))
            break;
        x ++;
    }
    cout << x << endl;
    return 0;
}

Python实现

def check(x):
    while x:
        if x % 16 <= 9:
            return False
        else:
            x //= 16
    return True

x = 2022
while True:
    if check(x):
        break
    x += 1
print(x)

2. 列号

题目描述

\(Excel\) 中,列的名称使用英文字母的组合。前 \(26\) 列用一个字母,依次为 \(A\)\(Z\),接下来 \(26 \times 26\) 列使用两个字母的组合,依次为 \(A\)\(Z\)。请问第 \(2022\) 列的名称是什么?

解题思路

\(1\ -\ 26:\ A\ -\ Z\)
\(26\ -\ 26*26:\ AA\ -\ ZZ\)
\(26*26\ -\ 26*26*26:\ AAA\ -\ ZZZ\)
....

从上面的序列可以观察到始终有个量是不会变化的,也就是每个列名的最后个字母,始终遵循一个字母表的循环,从本质上来说,这题就是一个二十六进制转换题。该题的步骤如下:

  1. 先确定最后一个字母;
    很简单就可以确认,直接2022 mod 26即可。
  2. 确认倒数第二个字母;
    倒数第二个字母的确认方式和步骤一类似,但是这里要处理一下中间过程。原因在于:倒数第二个字母实际上就是\(26*26\)个字母,不然不会产生下一个字母。
  3. 重复步骤一二直到对\(26\)取整为零即止。

代码实现

C++实现

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

int main()
{
    puts("BYT");
    return 0;
}

Python实现

def que2407(n):
    a = []          # 创建一个空的数组用于存储字母,在该数组中的列名的排列方式时逆序的。
    while n//26 :   # 只要n>26就说明列名至少有两个字母
        b = n%26
        a.append(chr(64+b))
        n //=26
        if n < 26:
            a.append(chr(64+n))     #Python中ASC码转字符串,因为n=1,2,3,4....,所以将初始值赋值为@的ASC码(64)
    return "".join(a[::-1])
print(que2407(2022))

3. 特殊日期

题目描述

对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 \(1900\)\(1\)\(1\) 日至 \(9999\)\(12\)\(31\) 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。

例如, \(2022\)\(11\)\(13\) 日满足要求,因为 \(2+0+2+2=(1+1)+(1+3)\)

请提交满足条件的日期的总数量。

解题思路

代码实现

C++实现

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

int days[] = {
    0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

bool is_leap(int y)
{
    return y % 400 == 0 || y % 4 == 0 && y % 100 != 0;
}

int daysOfMonth(int y, int m)
{
    if (m == 2)
        return is_leap(y) + 28;
    return days[m];
}

bool check(int x, int y, int z)
{
    int s1 = 0;
    while (x)
        s1 += x % 10, x /= 10;
    int s2 = 0;
    while (y)
        s2 += y % 10, y /= 10;
    while (z)
        s2 += z % 10, z /= 10;
    return s1 == s2;
}

int main()
{
    int res = 0;
    for (int i = 1900; i <= 9999; ++ i )
        for (int j = 1; j <= 12; ++ j )
            for (int k = 1; k <= daysOfMonth(i, j); ++ k )
                res += check(i, j, k);
    cout << res << endl;
    
    return 0;
}

Python实现

days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

def is_leap(y):
    return y % 400 == 0 or y % 4 == 0 and y % 100 != 0

def daysOfMonth(y, m):
    if m == 2 and is_leap(y):
        return 29
    return days[m]

def check(x, y, z):
    s1 = 0
    while x:
        s1 += x % 10
        x //= 10
    s2 = 0
    while y or z:
        s2 += y % 10
        s2 += z % 10
        y //= 10
        z //= 10
    return s1 == s2

res = 0
for i in range(1900, 10000):
    for j in range(1, 13):
        for k in range(1, daysOfMonth(i, j) + 1):
            res += check(i, j, k)
print(res)

2. 列号

题目描述

解题思路

代码实现

C++实现

Python实现

posted @ 2023-03-15 22:55  在读研狗  阅读(70)  评论(0)    收藏  举报