Seven-Segment Number Labels
National Olympiad — Regional round
Submission name: elmcnt.cpp
Problem summary
Label N consecutive computers with the decimal integers S,S+1,…,S+N−1. Digits use standard seven-segment displays: costs for 0 through 9 are 6,2,5,5,4,5,6,3,7,6. Count all segments required. Leading zeroes are not displayed; the number zero itself uses six segments.
Input
N S.
Output
Total segment count.
Constraints
0 ≤ N ≤ 10^17; 0 ≤ S ≤ 10^10. Archive metadata places this in the Regional round; the linked statement header says Municipal round, 5 February 2022.
Worked example
An independently prepared example for this explanation.
Input
2 0
Output
8
Solution analysis
- Define F(x) as the segment count for integers 0 through x; answer F(S+N−1)−F(S−1).
- Digit DP tracks whether the prefix is tight and whether a nonzero digit has started the number. Each state returns both the number of completions and their segment sum.
- A digit adds its cost times the number of suffix completions. At the end, a never-started number is zero and contributes six. Use 128-bit arithmetic for totals.
Why it works
Each number has exactly one padded digit representation in the DP. Leading padding contributes nothing; all displayed digits contribute once. Subtracting prefix totals leaves exactly the requested interval.
Watch out. The total can exceed signed 64-bit. N=0 must return zero without forming an invalid unsigned endpoint.
Commented C++17 solution
An independently written complete program with standard headers.
// Key idea: Each number has exactly one padded digit representation in the DP. Leading padding
// contributes nothing; all displayed digits contribute once.
#include<iostream>
#include<string>
#include<utility>
#include<functional>
using namespace std;
using I=__int128_t;
int cost[10]={6,2,5,5,4,5,6,3,7,6};
I prefix(long long x){
if(x<0){
return 0;
}
string s=to_string(x);
pair<I,I>memo[20][2];
bool used[20][2]={};
function<pair<I,I>(int,bool,bool)>go=[&](int p,bool tight,bool started)->pair<I,I>{
if(p==(int)s.size()){
return {1,started?0:6};
}
if(!tight&&used[p][started]){
return memo[p][started];
}
I cnt=0,sum=0;
int lim=tight?s[p]-'0':9;
for(int d=0;d<=lim;d++){
bool ns=started||d;
auto[c,v]=go(p+1,tight&&d==lim,ns);
cnt+=c;
sum+=v+c*(ns?cost[d]:0);
}
pair<I,I>res={cnt,sum};
if(!tight){
used[p][started]=true;
memo[p][started]=res;
}
return res;
};
return go(0,true,false).second;
}
void print(I x){
if(x>=10){
print(x/10);
}
cout<<char('0'+x%10);
}
int main(){
long long n,s;
cin>>n>>s;
print(n?prefix(s+n-1)-prefix(s-1):0);
cout<<'\n';
}