cppAcademy
FROM LEARNING TO COMPETING

Intermediate.
Put your skills to the test.

Bulgarian Informatics Group D · 2007–2026

270 independently explained problems: 54 Municipal, 54 Regional, 105 National Olympiad and 57 Autumn Tournament tasks. Start with the easier tasks and work upwards. Difficulty labels are learning estimates, not official ratings; Group D also includes challenging national-level problems. The six 2017 National tasks shared by Groups C and D use their existing permanent URLs. Years follow Arena’s competition-season labels. Source clarifications and special grader requirements are noted on affected tasks.
GROUP D2018 · MediumExhaustive search

Change Exactly Two Digits

Autumn Tournament (2018)

Submission name: changenumber.cpp

Problem summary

Change exactly two digit positions in a possibly signed decimal integer to obtain the largest possible integer divisible by 6. Keep its sign and number of digits; a changed digit must differ from its original value. Do not print a leading plus sign.

Source clarification. The PDF does not explicitly discuss leading zeroes in the modified number. The official author implementation preserves a nonzero first digit; this solution follows that intended convention.

Input

One integer with an optional + or − sign.

Output

The largest resulting multiple of 6.

Constraints

The input contains 2 to 100 digits. The resulting number has no leading zero.

Worked example

Official statement sample.

Input

-4321

Output

-1320

Solution analysis

  1. Use a string: 100-digit integers do not fit built-in numeric types. A multiple of 6 must have an even final digit and a digit sum divisible by 3.
  2. Enumerate the two distinct changed positions and their two replacement digits. Reject unchanged replacements, leading zeroes, odd last digits, and digit sums not divisible by 3. The sum can be updated from the original sum in constant time.
  3. All remaining candidates have the same length. For a positive input, lexicographically larger digits give a larger number. For a negative input, choose the lexicographically smallest absolute value instead. For −4321, changing 4 to 1 and the final 1 to 0 produces −1320; its digit sum is 6 and it is even.
  4. The code mutates one candidate string and restores its changed positions after trying each pair. It copies a string only when a valid candidate improves the best. This exhaustive method is straightforward enough for at most 100 digits.

Why it works

Every permitted result changes a unique pair of positions to two different replacement digits, so it is enumerated. The parity and digit-sum tests are equivalent to divisibility by 6. Equal-length lexicographic comparison orders positive magnitudes, reversed for negatives; selecting the best valid candidate therefore maximizes the signed result.

Complexity: O(L³·100) worst-case time: O(L²) pairs, at most 100 replacements, and O(L) string comparison. O(L) extra space. With L ≤ 100 this bounded exhaustive search is practical.

Watch out. Exactly two positions must change, even when the input already divides by 6. For a negative number maximize the signed value by minimizing its magnitude. Preserve the sign, prohibit a leading zero, and do not parse 100 digits into an integer.

Commented C++17 solution

An independently written complete program with standard headers.

#include<iostream>
#include<string>
using namespace std;
int main(){
    string digits;
    cin>>digits;
    bool negative=digits[0]=='-';
    if(digits[0]=='-'||digits[0]=='+'){
        digits.erase(digits.begin());
    }
    int length=static_cast<int>(digits.size());
    int digitSum=0;
    for(char digit:digits){
        digitSum+=digit-'0';
    }
    string candidate=digits;
    string best;
    for(int first=0;first<length;first++){
        for(int second=first+1;second<length;second++){
            for(char a='0';a<='9';a++){
                if(a==digits[first]||(first==0&&a=='0')){
                    continue;
                }
                candidate[first]=a;
                for(char b='0';b<='9';b++){
                    if(b==digits[second]){
                        continue;
                    }
                    candidate[second]=b;
                    int newSum=digitSum+a-digits[first]+b-digits[second];
                    if((candidate.back()-'0')%2!=0||newSum%3!=0){
                        continue;
                    }
                    // Negative numbers reverse the order of their magnitudes.
                    if(best.empty()||(negative?candidate<best:candidate>best)){
                        best=candidate;
                    }
                }
                candidate[second]=digits[second];
            }
            candidate[first]=digits[first];
        }
    }
    if(negative){
        cout<<'-';
    }
    cout<<best<<'\n';
}

Source: Arena Olimpiici ↗