#include <bits/stdc++.h>
using namespace std;
// Fast counting of distinct S(x) = sorted digits of concat(x, x+1) for x=1..n
// Complexity: O( sum_{m=1..L} C(m+8,8) * m * 9 ) ~ 4e6 for n up to 1e9
// Custom hash for array<int,10>
struct ArrHash {
size_t operator()(array<int,10> const &a) const noexcept {
// FNV-like hash
uint64_t h = 146527;
for (int i = 0; i < 10; ++i) {
h = (h ^ a[i]) * 1099511628211ULL;
}
return (size_t)h;
}
};
// Build the lexicographically smallest string of length 'len' from digit counts rem[0..9],
// with the constraint that the first character is non-zero.
string build_min_prefix(array<int,10> rem, int len) {
string s;
s.reserve(len);
// find smallest non-zero digit for first char
for (int d = 1; d <= 9; ++d) {
if (rem[d] > 0) {
s.push_back('0' + d);
rem[d]--;
break;
}
}
// then zeros
int zeros = rem[0];
for (int i = 0; i < zeros; ++i) s.push_back('0');
rem[0] = 0;
// then remaining digits in ascending order
for (int d = 1; d <= 9; ++d) {
while (rem[d] > 0) {
s.push_back('0' + d);
rem[d]--;
}
}
return s;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long n;
cin >> n;
string n_str = to_string(n);
int L = n_str.size();
// Count boundary cases: x = 10^m - 1, where 10^m -1 <= n
long long B = 0;
long long p = 10;
while (p - 1 <= n) {
B++;
if (p > n / 10) break;
p *= 10;
}
long long total = B;
vector<long long> ten(L+2,1);
for (int i = 1; i <= L+1; ++i) ten[i] = ten[i-1] * 10;
// For each digit-length m
for (int m = 1; m <= L; ++m) {
long long lo = ten[m-1];
long long up_full = ten[m] - 2; // last full-block x
bool is_full = (n >= up_full);
if (!is_full && n < lo) break; // no valid x of this digit-length
unordered_set<array<int,10>, ArrHash> seen;
array<int,10> c;
c.fill(0);
// recursive generation of c counts by combinations with replacement
function<void(int,int)> dfs = [&](int pos, int start) {
if (pos == m) {
if (c[0] == m) return; // would be leading zeros
// for each run of trailing 9's
for (int r = 0; r < m && c[9] >= r; ++r) {
// for each digit to increment a
for (int a = 0; a < 9; ++a) {
if (c[a] == 0) continue;
// feasibility: ensure non-zero MSB among rem
int nz_rem = m - 1 - r;
array<int,10> rem = c;
rem[9] -= r;
rem[a] -= 1;
if (nz_rem > 0) {
int sum_nz = 0;
for (int d = 1; d <= 9; ++d) sum_nz += rem[d];
if (sum_nz == 0) continue;
} else {
// r = m-1: only a is MSB
if (a == 0) continue;
}
// if partial top block, ensure existence of x <= n
if (!is_full && m == L) {
string pref = build_min_prefix(rem, nz_rem);
string x_str = pref + char('0'+a) + string(r, '9');
// x_str length = m = L = n_str.size()
if (x_str > n_str) continue;
}
// build combined digit-count tot
array<int,10> tot;
for (int i = 0; i < 10; ++i) tot[i] = 2 * c[i];
tot[a] -= 1;
tot[a+1] += 1;
tot[9] -= r;
tot[0] += r;
seen.insert(tot);
}
}
return;
}
for (int d = start; d < 10; ++d) {
c[d]++;
dfs(pos+1, d);
c[d]--;
}
};
dfs(0, 0);
total += (long long)seen.size();
}
cout << total << "\n";
return 0;
}