2022蓝桥杯题目——“山”

目录

题目

要求

思路

暴力解法

缺点

技巧

中间一部分

末尾一部分

开头一部分

最后

代码部分讲解

 最终所有代码


题目

这天小明正在学数数。

他突然发现有些正整数的形状像一挫 “山”, 比如 123565321、145541123565321它 们左右对称 (回文) 且数位上的数字先单调不减, 后单调不增。

小朋数了衣久也没有数完, 他惒让你告诉他在区间 [2022,2022222022] 中有 多少个数的形状像一座 “山”。

要求

填空题,要写出答案即可

思路

暴力解法

思路非常简单,提取每一个数字的位数来判断两边是否相等,并且判断前一半是否是单调不减的

缺点

缺点是每一个都要计算会十分麻烦,计算量直接来到了10的10次方,估计要运行一分多钟,虽然题目只要求答案,你可以运行完成后直接打印答案,但是还有更加巧妙的思路

技巧

中间一部分

由于1111~999999999可以进行变化

取前一半数字,只要他满足单调不减就行了

比如如果五位数

取前一半也就是三个数字

124时,后面必定有且只有一种数字(21)与其对应,形成12421

所以我们只需算前一半的数字即可

也就是11~99999

这一个变化带来速度提升是巨大的

时间直接缩小几个数量级

末尾一部分

在末尾中2022222022这个数字比较特殊

因为开头为2所以前一位也必须不比2小的数

显然2后面是0无法满足条件

所以最高位2必须要变小,然而不能为0

所以只能是1(个位同时也必须是1),而且中间部分位数可以随便变化(因为1111111111~1999999991属于2022~2022222022)

于是可以把他看成为8位数字,然后再算一次加起来就行了

开头一部分

开头没什么好说的

2022~9999

提取前一半位数,同时由于最小为2,所以百位也必须是不比2小的数字(2,3,4,5,6,7,8,9)

以此类推可以心算出来开头部分(2022~9999)的符合条件的个数为8+7+6+5+4+3+2+1

最后

最后全部加起来

代码部分讲解

中间一部分加末尾一部分为

       int sum_2 = 0;
        int sum_3 = 0;
        int sum_4 = 0;
        if (i == 10)
        //同时1111111111-2022222022的情况与111111111-99999999一致
            sum_2 = 9 / 2;
        else if (i % 2 == 0)
            sum_2 = i / 2;
        else 
            sum_2 = i / 2+1;
        for (int j = 0; j <= sum_2-1; j++)
        {
            sum_3 = sum_3 + 1*pow(10, j);
            sum_4 = sum_4 + 9 * pow(10, j);
        }
        for (int z = sum_3; z <= sum_4; z++)
        {
            if (Function_1(z))
            {
                max++;
            }
        }

 由于奇数位数的数字取一半用的是进一法,而c/c++用的是退一法,所以对奇数位数的数字做出分类以及改变

其中pow代表的是指数公式(前面为底数,后面为指数),sum3和sum4分别表示各个位数的值的最大和最小值,方便通过访问来遍历数组的元素

当位数个数为10个时也就是到了“末尾一部分”的数字了

这时候可以直接当做8,当成8位数来计算就可以了

同时判断是否递增的函数可以用循环来判断

bool Function_1(int n)
{
    int x_1 = 9;
    int x_2 = 9;
    int y_1 = 9;
    while (n > 0)
    {
        int y_1 = x_1;
        x_1 = n % 10;
        x_2 = y_1;
        n = n / 10;
        if (x_1 > x_2)
        {
            return false;
        }
    }
    return true;
}

 最终所有代码

#include <iostream>
#include<math.h>
using namespace std;
bool Function_1(int n)
{
    int x_1 = 9;
    int x_2 = 9;
    int y_1 = 9;
    while (n > 0)
    {
        int y_1 = x_1;
        x_1 = n % 10;
        x_2 = y_1;
        n = n / 10;
        if (x_1 > x_2)
        {
            return false;
        }
    }
    return true;
}
int main()
{
    int max = 0;
    int sum_1=0;
    max = 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1;
    //2022-9999的情况列举出来
    for (int i = 5; i <= 10; i++)
    {
        //11111-99999999的情况(只需要计算出前面一半各个数字单调递增即可
        int sum_2 = 0;
        int sum_3 = 0;
        int sum_4 = 0;
        if (i == 10)
        //同时1111111111-2022222022的情况与111111111-99999999一致
            sum_2 = 9 / 2;
        else if (i % 2 == 0)
            sum_2 = i / 2;
        else 
            sum_2 = i / 2+1;
        for (int j = 0; j <= sum_2-1; j++)
        {
            sum_3 = sum_3 + 1*pow(10, j);
            sum_4 = sum_4 + 9 * pow(10, j);
        }
        for (int z = sum_3; z <= sum_4; z++)
        {
            if (Function_1(z))
            {
                max++;
            }
        }
    }
    cout << max << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mumuemhaha/article/details/132124484