题目
题目链接:http://codeforces.com/contest/625/problem/D
题目来源:cf#342
简要题意:给定一个大整数,问是否能由一个无前导零的整数正序,反向相加获得。
题解
这个题非常难处理,需要考虑相当多边边角角的细节。
基本的思路就是从两边向中间去构造。
难点一在于进位,这个可以依靠借和送来解决,分情况。
难点二在于开头无法送位,这个需要特判。
难点三在于判断非法上,边角的条件较多。
总的来说题目易懂,但是解法上需要慎重考虑,好题。
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int N = 1E5+5;
char s[N];
int a[N];
char out[N];
bool solve(int n) {
for (int l = 0, r = n-1; l <= r; l++, r--) {
// r向前借一位
if (a[l] >= a[r]+10) {
a[r-1]--;
a[r] += 10;
}
// l向后送一位
if (a[l] == a[r]+1) {
a[l]--;
a[l+1] += 10;
}
if (a[l] != a[r]) return false;
// 让高位大,否则11出错
int temp = (a[l]+1)/2;
out[l] = temp + '0';
out[r] = a[l] - temp + '0';
}
// 不加的话100会出错
if (!a[0]) return false;
// 奇数位则中间的必须为偶数
if ((n&1) && (a[n/2]&1)) return false;
for (int i = 0; i < n; i++) {
if (a[i] < 0 || a[i] > 18) return false;
}
out[n] = '\0';
puts(out);
return true;
}
int main() {
while (gets(s)) {
int n = strlen(s);
for (int i = 0; i < n; i++) {
a[i] = s[i]-'0';
}
if (solve(n)) continue;
// 1打头最高位无法送位,特判
if (s[0] == '1' && n != 1) {
for (int i = 1; i < n; i++) {
a[i-1] = s[i]-'0';
}
a[0] += 10;
if (solve(n-1)) continue;
}
puts("0");
}
return 0;
}