这天小明正在学数数。 他突然发现有些正整数的形状像一挫 “山”, 比如 123565321、145541123565321它 们左右对称 (回文) 且数位上的数字先单调不减, 后单调不增。 小朋数了衣久也没有数完, 他惒让你告诉他在区间 [2022,2022222022] 中有 多少个数的形状像一座 “山”。
填空题,要写出答案即可
思路非常简单,提取每一个数字的位数来判断两边是否相等,并且判断前一半是否是单调不减的
缺点是每一个都要计算会十分麻烦,计算量直接来到了10的10次方,估计要运行一分多钟,虽然题目只要求答案,你可以运行完成后直接打印答案,但是还有更加巧妙的思路
由于1111~999999999可以进行变化
取前一半数字,只要他满足单调不减就行了
比如如果五位数
取前一半也就是三个数字
124时,后面必定有且只有一种数字(21)与其对应,形成12421
所以我们只需算前一半的数字即可
也就是11~99999
这一个变化带来速度提升是巨大的
时间直接缩小几个数量级
在末尾中2022222022这个数字比较特殊
因为开头为2所以前一位也必须不比2小的数
显然2后面是0无法满足条件
所以最高位2必须要变小,然而不能为0
所以只能是1(个位同时也必须是1),而且中间部分位数可以随便变化(因为11111111111999999991属于20222022222022)
于是可以把他看成为8位数字,然后再算一次加起来就行了
开头没什么好说的
2022~9999
提取前一半位数,同时由于最小为2,所以百位也必须是不比2小的数字(2,3,4,5,6,7,8,9)
以此类推可以心算出来开头部分(2022~9999)的符合条件的个数为8+7+6+5+4+3+2+1
最后全部加起来
代码部分讲解
中间一部分加末尾一部分为
|
|
由于奇数位数的数字取一半用的是进一法,而c/c++用的是退一法,所以对奇数位数的数字做出分类以及改变
其中pow代表的是指数公式(前面为底数,后面为指数),sum3和sum4分别表示各个位数的值的最大和最小值,方便通过访问来遍历数组的元素
当位数个数为10个时也就是到了"末尾一部分"的数字了
这时候可以直接当做8,当成8位数来计算就可以了
同时判断是否递增的函数可以用循环来判断
|
|
最终所有代码
|
|