题解:AT_abc387_e [ABC387E] Digit Sum Divisible 2

AtCoder Beginner Contest 387 E - Digit Sum Divisible 2题解

题目描述

正整数 \(n\) 的位数和定义为 \(n\) 写成十进制时的位数和。例如,\(2025\) 的位数和是 \(2 + 0 + 2 + 5 = 9\)

如果一个正整数 \(n\) 能被它的数位和整除,那么这个正整数 \(n\) 就叫做好整数。例如,\(2025\) 是一个好整数,因为它能被其数位和 \(9\) 整除。

如果 \(a\)\(a+1\) 都是好整数,那么一对正整数 \((a, a+1)\) 称为孪生好整数。例如,\((2024, 2025)\) 就是一对孪生好整数。

给你一个正整数 \(N\)。请找出一对孪生好整数 \((a, a + 1)\),使得 \(N \leq a\)\(a + 1 \leq 2N\)。如果不存在这样的一对,输出 \(-1\)

思路

对于小数据,我们进行暴力。而对于大数据,我们只需要构造一个有规律的、比较特殊的数。

首先我们知道:

  • 一个数能被 \(8\) 整除当且仅当它的后三位能被 \(8\) 整除。

  • 一个数能被 \(9\) 整除当且仅当它的数位之和能被 \(9\) 整除。

由此, 我们进行构造。

令一个好整数 \(a\) 的数位之和为 \(8\),且个位不为 \(9\)

根据上面的两个性质和好整数的定义,我们可以确定:

\(a\)\(8\) 的倍数,\(a+1\)\(9\) 的倍数且是一个好整数。

\((a,a+1)\) 是一对孪生好整数。

归纳一下,使 \((a,a+1)\) 是一对孪生好整数的条件有:

  • \(a\) 的是 \(8\) 的倍数。

  • \(a\) 的数位之和是 \(8\)

  • \(n \le a < 2n\)

那么,什么样的 \(a\) 既是特殊的又满足上面的条件呢?仔细思考,我们发现当 \(a\) 的后三位全部是 \(0\) 时,既特殊又满足条件。

接下来我们开始分类讨论。

先考虑特殊情况。若 \(n\) 除了第一位之外全是 \(0\),即 \(n = \overline{x00\dots00}\)。显然,在构造 \(a\) 时,我们可以让 \(a\) 的第一位仍为 \(x\),第二位为 \(8-x\)。代码写为 cout << x << 8 - x, zero_out(len - 2);。其中 zero_out 是输出多少个 \(0\)。当然,这是建立在 \(x \ne 9\) 的基础上的。而当 \(x=9\) 时,我们可以让 \(a = \overline{1700\dots00}\)。代码为 cout << 17, zero_out(len - 1);

\(n\) 只是一个普通的数呢?我们发现只需要考虑它的前两位即可,我们设为 \(x\)\(y\)。当 \(x=9\) 时,与上面的一样。cout << 17, zero_out(len - 1);。当 \(x=8\) 时,cout << 107, zero_out(len - 2);。当 \(x \ne 1\) 时,cout << x + 1 << 8 - x - 1, zero_out(len - 2);。当 \(x=1\)\(y \ge 5\) 时,cout << x + 1 << 8 - x - 1, zero_out(len - 2);。若以上条件都不成立,cout << 17 , zero_out(len - 2);

至此,我们已经全部分类讨论完了,这是完整代码。

代码

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int N = 1e5 + 5;

string n;// 由于 n 非常大,我们只能用字符串读入 

// 数据小时判断是否为好整数 
bool is_good(int x){
	int sum = 0, p = x;
	while (p) sum += p % 10, p /= 10;
	return x % sum == 0;
}

// 输出 0 
void zero_out(int num){
	for (int i = 1; i <= num; i++) cout << 0;
}

int main(){
	cin.tie(0)->sync_with_stdio(0);

	cin >> n;
	
	int len = n.size();
	
	// 小数据暴力 
	if (len <= 6){
		int now_n = 0;
		for (int i = 0; i < len; i++)
			now_n = now_n * 10 + n[i] - '0';
		for (int i = now_n; i < 2 * now_n; i++){
			if (is_good(i) && is_good(i + 1)){
				cout << i;
				return 0;
			}
		}
		cout << -1;
		return 0;
	}
	
	/*                        ________
	考虑 n 的特殊情况,即 n = x00...00 */ 
	bool zero = 0;
	for (int i = len - 1; i >= 0; i--)
		if (n[i] == '0'){
			zero = 1;
			break;
		}
	
	// 分类讨论 
	if (!zero){
		int x = n[0] - '0';
		if (x != 9)
			cout << x << 8 - x, zero_out(len - 2);
		else
			cout << 17, zero_out(len - 1);
	}
	else {
		int x = n[0] - '0';
		int y = n[1] - '0';
		if (x == 9)
			cout << 17, zero_out(len - 1);
		else if (x == 8)
			cout << 107, zero_out(len - 2);
		else if (x != 1 || (x == 1 && y >= 5))
			cout << x + 1 << 8 - x - 1, zero_out(len - 2);
		else
			cout << 17, zero_out(len - 2);
	}

	return 0;
}

posted @ 2025-01-10 22:57  chaqjs  阅读(45)  评论(0)    收藏  举报