Next Number with Digit GCD Greater than One
National Olympiad — National round (2020 season)
Submission name: gcdd.cpp
Problem summary
Find the smallest integer strictly greater than a very long decimal n whose digits have gcd greater than one.
Input
Positive decimal n without leading zeroes.
Output
The smallest qualifying successor.
Constraints
1 ≤ number of input digits < 1000000.
Worked example
Input and output for the worked example discussed below.
Input
34
Output
36
Solution analysis
- A common digit gcd greater than one has a prime factor among 2,3,5,7, since every nonzero decimal digit is at most 9. Find a successor separately using only digits divisible by each prime.
- For one allowed set, preserve the longest valid prefix and stop at its first forbidden digit. Increase that position to the smallest allowed greater digit, backtracking left if necessary. If all digits already qualify, begin at the last position to force strict increase.
- After increasing a position fill the suffix with zeroes. If no same-length successor exists, use leading p followed by zeroes. Compare the four candidates by length, then lexicographically.
- For 34, even digits give 40 while multiples-of-3 digits give 36, the global minimum. Zero digits are valid since gcd(0,x)=x.
Why it works
Every valid successor belongs to a prime-restricted digit set, and the rightmost feasible increase with a minimal suffix finds the smallest successor in that set.
Watch out. Do not parse the input into a bounded integer. The successor must be strict even when n already qualifies, and may need an additional digit.
Commented C++17 solution
An independently written complete program with standard headers.
// Every valid successor belongs to a prime-restricted digit set, and the rightmost feasible increase with a
// minimal suffix finds the smallest successor in that set.
#include<iostream>
#include<string>
using namespace std;
string nextAllowed(const string&number,int prime){
int length=number.size();
int position=0;
while(position<length&&(number[position]-'0')%prime==0){
position++;
}
if(position==length){
position--;
}
for(;position>=0;position--){
for(int digit=number[position]-'0'+1;digit<=9;digit++){
if(digit%prime==0){
string answer=number.substr(0,position);
answer+=char('0'+digit);
answer+=string(length-position-1,'0');
return answer;
}
}
}
return string(1,char('0'+prime))+string(length,'0');
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
string number;
cin>>number;
string answer;
for(int prime:{2,3,5,7}){
string candidate=nextAllowed(number,prime);
if(answer.empty()||candidate.size()<answer.size()||
(candidate.size()==answer.size()&&candidate<answer)){
answer=candidate;
}
}
cout<<answer<<'\n';
}