CF1433A Boring Apartments 题解

Content

我们把仅由一个或多个相同的数位组成的数字叫作“无聊的数字”。我们把 \(\leqslant 10000\) 的这种数字按照以下规则排列:

  • 首先,将仅由 \(1\) 组成的 \(\leqslant 10000\) 的“无聊的数字”按照升序排列:\(1,11,111,1111,...\)
  • 再将仅由 \(2\) 组成的 \(\leqslant 10000\) 的“无聊的数字”按照升序排列:\(2,22,222,2222,...\)
  • 以此类推。

给出 \(t\) 次询问,每次询问给定一个无聊的数字 \(x\),请求出当数列排到 \(x\) 时,\(x\) 以及前面所有的“无聊的数字”的位数之和。

数据范围:\(1\leqslant t\leqslant 36,1\leqslant x\leqslant 9999\)

Solution

虽然翻译可能和原来题面有些许出入,但是不会影响做题的。

我们假设现在给出的 \(x\) 仅由数字 \(a\) 构成,那么前面肯定 \(10(a-1)\) 次,这是由于你在前面的仅由 \(1,2,...,a-1\) 构成的“无聊的数字”中,每个数字按了 \(1+2+3+4=10\) 次,所以就是 \(a-1\) 次,然后,我们根据这个数的位数 \(y\),我们可以推出当前的数字一共按了 \(1+2+...+y=\dfrac{y(y+1)}{2}\) 次,所以一共按了 \(10(a-1)+\dfrac{y(y+1)}{2}\) 次。

官方题解是直接字符串读入然后提取构成的数字和数位的,下面给出一种不同于官方题解的具体实现:我们可以直接拿 \(10\) 对这个数取模得到其个位数,根据“无聊的数字”的定义可知它就是由这个个位数组成的。然后我们通过分离数位得到其位数,最后直接按照上面的公式计算即可。虽然效率会有些低,但是对于这道题目是足够的了。

Code

int t, x;

int main() {
	//This program is written in Windows 10 by Eason_AC
	getint(t);
	while(t--) {
		getint(x);
		int p = x, digit = 0;
		while(p) {
			digit++;
			p /= 10;
		}
		printf("%d\n", (x % 10 - 1) * 10 + (digit + 1) * digit / 2);
	}
	return 0;
}
posted @ 2021-12-16 15:14  Eason_AC  阅读(45)  评论(0)    收藏  举报