CodeForces 625D Finals in arithmetic

Posted on By 二价氢

题目大意

将一个没有前导零的数\(x\)翻转后的数记为\(x_f\),如\(x = 123\),则\(x_f = 321\),现在给定一个数\(n\),求\(x\),使得\(x + x_f = n\)

做法

显然,我们可以构造出一个答案

假设这个n的十进制表示为\((a_{m-1}a_{m-2}\ldots a_{1}a_{0})_{10}\),那么通过观察\(a_{m-1}\)与\(a_0\),我们可以分如下几个情况分析:

  1. \(a_{m-1} = a_0\),显然我们可以得出最高位与最低位的和为\(a_0\)
  2. \(a_{m-1} = a_0 + 1\),可以得出最高位与最低位的和为\(a_0\),同时次高位与次低位的和大于10

分情况讨论这两种即可,然后这里有很多细节需要处理。

同时还要注意答案的位数可能与\(n\)的位数相等,或比\(n\)的位数小1

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100005;
char str[maxn];
int sss[maxn], ans1[maxn], ans2[maxn];
int len;
int l, r;
bool getAnswer(int _l, int _r) {
	memset(ans1, 0, sizeof(ans1));
	for (int i = 0; i < len; i++) sss[i] = str[i] - '0';
	l = _l;r = _r;
	if (l == 1) {
		if (sss[0] == 1) {
			sss[l] += 10;
			sss[r] += 10;
			sss[r - 1]--;
		} else
			return false;
	}
	for (; l <= r; l++, r--) {
		while (sss[l] < 0) sss[l] += 10;
		while (sss[r] < 0) {sss[r - 1]--;sss[r] += 10;}
		if (sss[l] == sss[r] + 10 || sss[l] == sss[r] + 11) {sss[r - 1]--;sss[r] += 10;}
		//cerr << sss[l] << ',' << sss[r] << endl;
		if (sss[l] == sss[r]) {
			ans1[r] = sss[l] / 2;
			ans1[l] = sss[l] - ans1[r];
			if (ans1[r] > 9 || ans1[l] > 9) return false;
			if (l == r) {if (sss[l] % 2 != 0) return false;}
		} else if (sss[l] == sss[r] + 1) {
			if (l == r || l == r - 1) return false;
			sss[l]--;
			ans1[r] = sss[r] / 2;
			ans1[l] = sss[r] - ans1[r];
			if (ans1[r] > 9 || ans1[l] > 9) return false;
			sss[l + 1] += 10;
		} else {
			return false;
		}
	}
	return ans1[_l] != 0;
}
int main() {
	ios::sync_with_stdio(0);
	cin >> str;
	len = strlen(str);
	if (getAnswer(0, len - 1)) {
		for (int i = 0; i < len; i++) cout << ans1[i];
		cout << endl;
	} else if (len > 1 && getAnswer(1, len - 1)) {
		for (int i = 1; i < len; i++) cout << ans1[i];
		cout << endl;
	} else {
		cout << "0\n";
	}
	return 0;
}