abc234_e Arithmetic Number 题解
Arithmetic Number
题意
一个数 \(n\) 被称为等差数当且仅当它满足以下条件:
- 令 \(n=\overline{d_1d_2 \dots d_k}\),\(k\) 为 \(n\) 的位数。
- \(d_2 - d_1=d_3 - d_2 = \dots = d_k - d_{k-1}\),即序列 \(d\) 为等差数列。
- 注意,当 \(k=1\) 时 \(d\) 也算做等差数列。
给定一个整数 \(X\),求一个最小的 \(Y\) 使得 \(Y \geqslant X\) 并且 \(Y\) 为等差数。
思路
暴力
一个一个数去枚举,每枚举一个就做一次判断,找到第一个等差数,输出。
正解
暴力时间复杂度肯定过不了。
首先,我们可以发现,等差数是非常少的,直接枚举会去判断太多的不合法答案。
但是,我们知道,等差数是必须长成一个等差数列的样子,也就是说,只要枚举一下首项和公差,就能推出整个等差数列。
但还有个问题,我们不清楚它要多少位啊 (其实不知道要多少位也是可以做的)。
我们知道,\(n\) 位数里面最大的数肯定是 \(10^n-1\),整个数由 \(n\) 个 \(9\) 组成,这时,我们就会惊喜地发现:它必然是一个等差数。
所以,只要取这个等差数列的前 \(k\) 位(\(k\) 为 \(X\) 的位数),判断它是否大于等于 \(X\) 即可,如果不成立,那么也不用考虑选更多位了,这个等差数列一定不是构成答案的等差数列
最后只需要注意判断等差数列中不能出现大于 \(9\) 或小于 \(0\) 的数即可。
Code
点击查看代码
#include <iostream>
using namespace std;
long long x, y, le; // 记得开 long long
int t, flag, sum, st;
int main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> x;
le = x;
while (le) { // 求 x 的位数
st = le % 10, le /= 10;
sum++;
}
for (int i = st; i <= 9; i++) { // 优化一下,枚举首项
for (int d = -9; d <= 9; d++) { // 枚举公差
y = i, t = i, flag = 1;
for (int j = 1; j < sum; j++) { // 枚举每一位
t += d;
if (t > 9 || t < 0) { // 判断不合法的情况
flag = 0;
break;
}
y = y * 10 + t;
}
if (flag && y >= x) { // 是一个大于 X 的等差数
cout << y;
return 0; // 结束
}
}
}
return 0;
}