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;
}
posted @ 2023-05-17 21:05  wnsyou  阅读(20)  评论(0编辑  收藏  举报