Sum of Digit Extremes
National Olympiad — Municipal round (2012 season)
Submission name: bplusc.cpp
Problem summary
Rearrange all digits of positive integer a to obtain the smallest positive integer b and the largest integer c. Find b+c. Leading zeros are not allowed.
Input
The decimal representation of a.
Output
The exact decimal sum b+c.
Constraints
75% of tests: 0<a<10^15. The remaining tests have 10^20<a<10^50.
Worked example
An independently prepared example for this explanation.
Input
201
Output
312
Solution analysis
- Read a as text, since 50 digits exceed the built-in integer types. Sort its digits increasingly for b and decreasingly for c.
- If the increasing order starts with zero, swap its first digit with the first nonzero digit. This puts the smallest possible nonzero digit first, followed by all remaining digits in increasing order.
- For 201 the orders become 102 and 210. Add from right to left with a carry to obtain 312. Decimal string addition also handles a final carry that increases the result length.
Why it works
The first differing digit determines numeric order among equal-length valid numbers. Therefore the greedy smallest nonzero first digit and sorted suffix minimize b, and descending digits maximize c. Standard column addition produces their exact sum.
Watch out. Do not parse the input as a 64-bit integer. All digits, including every zero, must be used exactly once.
Commented C++17 solution
An independently written complete program with standard headers.
#include<iostream>
#include<string>
#include<algorithm>
// Algorithm: Read a as text, since 50 digits exceed the built-in integer types.
using namespace std;
int main(){
string smallest;
cin>>smallest;
sort(smallest.begin(),smallest.end());
string largest=smallest;
reverse(largest.begin(),largest.end());
if(smallest[0]=='0'){
size_t firstNonzero=smallest.find_first_not_of('0');
swap(smallest[0],smallest[firstNonzero]);
}
string answer;
int carry=0;
for(int i=static_cast<int>(smallest.size())-1;i>=0;i--){
int sum=smallest[i]-'0'+largest[i]-'0'+carry;
answer.push_back(static_cast<char>('0'+sum%10));
carry=sum/10;
}
if(carry!=0){
answer.push_back(static_cast<char>('0'+carry));
}
reverse(answer.begin(),answer.end());
cout<<answer<<'\n';
}