目录
题目
这天小明正在学数数。
他突然发现有些正整数的形状像一挫 “山”, 比如 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;
}