Автор задачі: | Андрій Холод (Connect) |
Підготував: | Андрій Холод (Connect) |
Розбір: | Андрій Холод (Connect) |
Ідея
Нехай число задано рядком .
Оскільки довжина числа може сягати 2 \cdot 10^5, працювати через стандартні цілі типи не вийде. Тому вся арифметика в рішенні робиться над рядками.
Ключове спостереження
Насправді достатньо перевірити лише два розрізи:
після першої цифри;
перед останньою цифрою.
Тобто кандидати такі:
s_0 + \text{value}(s[1..n-1]) та \text{value}(s[0..n-2]) + s_{n-1}
Іншими словами:
або ліва частина складається лише з першої цифри;
або права частина складається лише з останньої цифри.
Чому цього достатньо? Якщо ми ріжемо десь всередині, то обидві частини втрачають частину "ваги" старших розрядів. У десятковому записі старші цифри значно важливіші за молодші, тому оптимум досягається тоді, коли одна з частин має довжину 1, а друга містить майже все число.
Отже задача зводиться до порівняння всього двох варіантів. Cуму та порівняння двох великих чисел можна реалізувати за допомогою довгої арифметики, що і є рішенням.
Асимптотика
Кожен із двох кандидатів будується за , де — довжина рядка. Порівняння також працює за .
Отже маємо .
#include <bits/stdc++.h>
#include <random>
// fast_pragmas
//#pragma GCC optimize("O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize ("unroll-loops")
//#pragma GCC target("avx,avx2,tune=native")
// fast_pragmas ended
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("O3,unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
//#pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt")
using namespace std;
#define ull unsigned long long
#define ll long long
#define ld long double
#define speed ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define endl '\n'
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define pb push_back
#define ln log
#define lg log10
#define log log2
#define here cout<<"HERE"<<endl
const ll clasik = 5e5 + 7;
const ll mln = 1e6 + 7;
const ll mod = 1e9 + 7;
//const ll mod = 998244353;
const ll block_size = 450;
const ll INF = 1e17;
ll df[clasik];
string normalize(string s) {
int i = 0;
while (i + 1 < (int)s.size() && s[i] == '0') i++;
return s.substr(i);
}
string addDigit(string num, int d) {
int carry = d;
for (int i = (int)num.size() - 1; i >= 0 && carry > 0; i--) {
int cur = (num[i] - '0') + carry;
num[i] = char('0' + (cur % 10));
carry = cur / 10;
}
if (carry > 0) num.insert(num.begin(), char('0' + carry));
return normalize(num);
}
bool greaterNumber(string a, string b) {
if ((int)a.size() != (int)b.size()) return (int)a.size() > (int)b.size();
return a > b;
}
void solve() {
string s;
cin >> s;
int n = (int)s.size();
if (n == 2) {
int ans = (s[0] - '0') + (s[1] - '0');
cout << ans << endl;
return;
}
string option1 = addDigit(s.substr(1), s[0] - '0');
string option2 = addDigit(s.substr(0, n - 1), s[n - 1] - '0');
if (greaterNumber(option1, option2)) cout << option1 << endl;
else cout << option2 << endl;
}
signed main() {
//freopen("deciding_points_input.txt" , "r" , stdin);
//freopen("outputA.txt" , "w" , stdout);
speed;
int test;
test = 1;
//precalc();
//cin >> test;
for (int tt = 1; tt <= test; tt++) {
//cout << "Case #" << tt << ": ";
solve();
}
return 0;
}