2020 广工 新生程序设计竞赛 简要

E 好人hard

题意:输出1~n范围的所有回文数,\(1≤n≤10^{14}\).
大致思路如下。(用 dig 表示 n 的位数)代码片段 1 会按顺序输出\(0\sim\underbrace{99\dots 9}_{dig 个 9}\)范围内的回文数:

void rev(int n)
{
  int s=0;
  for (; n; n/=10) s = s*10 + n/10;
  return s;
}
int pow10[8] = {1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7};
...
for (int d=1; d<dig; ++d)
{ 
  int half = d/2;
  int lb = pow10[half], ub = pow10[half+1] - 1;
  if (d%2==1)
    for (int i=lb; i<=ub; ++i)
      for (int j=0; j<=9; ++j)
        cout << i << j << rev(i) << endl;
  else
    for (int i=lb; i<=ub; ++i)
      cout << i << rev(i) << endl;
}

为了避免输出 0,可以单独处理 1 位数的回文数:

if (n<10)
{
  for (int i=1; i<=n; ++i)
    cout << i << endl;
  return 0;
}
for (int i=1; i<=9; ++i) cout << i << endl;
for (int d=2; d<dig; ++d)
{...下同代码片段 1

在 d 等于 n 的位数 dig 时,需要额外处理边界。
考虑到 ≤n 的最大的回文数,该回文数的前 \(\lceil\frac{n}{2}\rceil\) 位与 n 的前 \(\lceil\frac{n}{2}\rceil\) 位相同(代码中记作 nHalf),有一种简单的写法是:
当 dig 为偶数时,把 i 的上界设置为 nHalf;
当 dig 为奇数时略复杂,把 i*10+j 的上界设置为 nHalf,实际写成代码时是用 if 搞搞

for (int d=2; d<dig; ++d) {...} //类似代码片段 1,但是循环边界改了
int half = dig / 2;
int nHalf = n / pow[half];
int lb = pow10[half], ub = pow10[half+1] - 1;
if (dig%2==1)
  for (int i=lb; i<=ub; ++i)
    for (int j=0; j<=9; ++j)
    {
      if (i*10+j>n) return 0;
      cout << i << j << rev(i) << endl;
    }
else
  for (int i=lb; i<=nHalf; ++i)
    cout << i << rev(i) << endl;
上一篇:在VUE中播放RTSP视频流?


下一篇:Iphone6 LightBlue测试BT4GMD-Q25P透传模块