- Translate each rule into one explicit state update.
- Maintain the invariant after every processed item.
- Return the accumulated state once all relevant input has been handled.
Code notes
- 97 lines of C++ from the credited upstream file 3519.cpp.
- The implementation visibly relies on sequence storage.
- 8 loop blocks detected.
Complexity
Count the number and nesting of passes over the input, then include the maintained containers in the memory estimate.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution {2 public:3 int countNumbers(const string& l, const string& r, const int b) {4 const vector<int> rDigits = convertToBaseB(r, b);5 vector<int> lDigits = convertToBaseB(l, b);6 vector<int> lMinus1Digits = convertToBaseB(decrement(l), b);7 padToSameLength(lDigits, rDigits);8 padToSameLength(lMinus1Digits, rDigits);9 return (countWithMem(rDigits, b) - countWithMem(lMinus1Digits, b) + kMod) %10 kMod;11 }12 13 private:14 static constexpr int kMod = 1'000'000'007;15 void padToSameLength(vector<int>& a, const vector<int>& b) {16 a.insert(a.begin(), b.size() - a.size(), 0);17 }18 19 int countWithMem(const vector<int>& digits, const int b) {20 vector<vector<vector<int>>> mem(digits.size(),21 vector<vector<int>>(2, vector<int>(b, -1)));22 return count(digits, 0, 0, true, b, mem);23 }24 25 int count(const vector<int>& num, int pos, int lastDigit, bool tight, int b,26 vector<vector<vector<int>>>& mem) {27 if (pos == num.size())28 return 1;29 30 if (mem[pos][tight][lastDigit] != -1)31 return mem[pos][tight][lastDigit];32 33 int res = 0;34 const int limit = tight ? num[pos] : b - 1;35 36 for (int d = lastDigit; d <= limit; d++) {37 const bool newTight = tight && (d == limit);38 res = (res + count(num, pos + 1, d, newTight, b, mem)) % kMod;39 }40 41 return mem[pos][tight][lastDigit] = res;42 }43 44 string decrement(string s) {45 for (int i = s.length() - 1; i >= 0; --i) {46 if (s[i] > '0') {47 --s[i];48 break;49 } else {50 s[i] = '9';51 }52 }53 return s[0] == '0' && s.length() > 1 ? s.substr(1) : s;54 }55 56 vector<int> convertToBaseB(const string& numStr, const int b) {57 vector<int> digits;58 vector<int> currentNum(1, 0);59 60 for (const char c : numStr) {61 const int d = c - '0';62 63 int carry = 0;64 for (int i = 0; i < currentNum.size(); ++i) {65 const long long product = (long long)currentNum[i] * 10 + carry;66 currentNum[i] = product % b;67 carry = product / b;68 }69 70 while (carry > 0) {71 currentNum.push_back(carry % b);72 carry /= b;73 }74 75 carry = d;76 for (int i = 0; i < currentNum.size() && carry; ++i) {77 const int sum = currentNum[i] + carry;78 currentNum[i] = sum % b;79 carry = sum / b;80 }81 82 while (carry > 0) {83 currentNum.push_back(carry % b);84 carry /= b;85 }86 }87 88 for (int i = currentNum.size() - 1; i >= 0; --i)89 digits.push_back(currentNum[i]);90 91 if (digits.empty())92 digits.push_back(0);93 94 return digits;95 }96};97