#include using namespace std; typedef long long ll; typedef std::pair P; typedef std::priority_queue, std::greater

> PQ; typedef std::complex cd; struct P3 { long long first, second, third; }; struct P3P { P first, second, third; }; struct compP3{ bool operator()(const P3 &p1,const P3 &p2) const { if (p1.first != p2.first) return p1.first < p2.first; if (p1.second != p2.second) return p1.second < p2.second; else return p1.third < p2.third; } }; struct gcompP3{ bool operator()(const P3 &p1,const P3 &p2) const { if (p1.first != p2.first) return p1.first > p2.first; if (p1.second != p2.second) return p1.second > p2.second; else return p1.third > p2.third; } }; const double PI = acos(-1.0); bool ckran(int a, int n) { return (a >= 0 && a < n); } void yn (bool f) { if (f) std::cout << "Yes" << '\n'; else std::cout << "No" << '\n'; } long long pplus(P a) { return a.first + a.second; } long long pminus(P a) { return a.first - a.second; } long long ptime(P a) { return a.first * a.second; } long long pdiv(P a) { return a.first / a.second; } template bool chmax(T& a, U b) { if (a < b) { a = b; return true; } else { return false; } } template bool chmin(T& a, U b) { if (a > b) { a = b; return true; } else { return false; } } template void outspace(std::vector a) { int n = a.size(); for (int i = 0; i < n; ++i) { std::cout << a[i]; if (i != n - 1) std::cout << " "; else std::cout << std::endl; } } void outspace(P a) { std::cout << a.first << ' ' << a.second << '\n'; } template void outendl(std::vector a) { int n = a.size(); for (int i = 0; i < n; ++i) { std::cout << a[i] << '\n'; } } void outdouble(long double a) { std::cout << std::fixed << std::setprecision(10) << a << std::endl; } std::vector lltovec(long long n, long long base = 10, long long minsize = -1) { std::vector res; while (minsize-- > 0 || n > 0) { res.push_back(n % base); n /= base; } // std::reverse(res.begin(), res.end()); return res; } long long vectoll(std::vector vec, long long base = 10) { long long res = 0; std::reverse(vec.begin(), vec.end()); for (auto i : vec) { res *= base; res += i; } std::reverse(vec.begin(), vec.end()); return res; } class uftree { private: std::vector union_find_tree; std::vector rank; std::vector nodes_count; public: uftree (int uftree_size) { union_find_tree.resize(uftree_size); rank.resize(uftree_size); nodes_count.resize(uftree_size); for (int i = 0; i < uftree_size; ++i) { union_find_tree[i] = i; rank[i] = 0; nodes_count[i] = 1; } } int find (int n) { if (union_find_tree[n] == n) return n; else { union_find_tree[n] = find(union_find_tree[n]); return union_find_tree[n]; } } void unite (int x, int y) { x = find(x); y = find(y); if (x == y) return; if (rank[x] > rank[y]) { union_find_tree[y] = union_find_tree[x]; nodes_count[x] += nodes_count[y]; } else { union_find_tree[x] = union_find_tree[y]; nodes_count[y] += nodes_count[x]; if (rank[x] == rank[y]) rank[y]++; } } bool connected (int x, int y) { x = find(x); y = find(y); return x == y; } long long groupCount (int x) { x = find(x); return nodes_count[x]; } }; class maxSegmentTree { int n; std::vector tree, lazy; const long long MINI = -4e18; public: maxSegmentTree(int size) { n = size; tree.assign(4 * n, MINI); lazy.assign(4 * n, MINI); } void push(int node, int start, int end) { if (lazy[node] != MINI) { // 遅延値を現在のノードに適用 tree[node] = std::max(tree[node], lazy[node]); // 子ノードに遅延値を伝播 if (start != end) { lazy[node * 2] = std::max(lazy[node * 2], lazy[node]); lazy[node * 2 + 1] = std::max(lazy[node * 2 + 1], lazy[node]); } // 現在のノードの遅延値をクリア lazy[node] = MINI; } } void updateRange(int l, int r, long long value, int node = 1, int start = 0, int end = -1) { if (end == -1) end = n - 1; push(node, start, end); if (start > r || end < l) { // 完全に範囲外 return; } if (start >= l && end <= r) { // 完全に範囲内 lazy[node] = value; push(node, start, end); return; } // 部分的に範囲が重なる場合 int mid = (start + end) / 2; updateRange(l, r, value, node * 2, start, mid); updateRange(l, r, value, node * 2 + 1, mid + 1, end); tree[node] = std::max(tree[node * 2], tree[node * 2 + 1]); } long long queryRange(int l, int r, int node = 1, int start = 0, int end = -1) { if (end == -1) end = n - 1; push(node, start, end); if (start > r || end < l) { // 完全に範囲外 return MINI; } if (start >= l && end <= r) { // 完全に範囲内 return tree[node]; } // 部分的に範囲が重なる場合 int mid = (start + end) / 2; long long leftQuery = queryRange(l, r, node * 2, start, mid); long long rightQuery = queryRange(l, r, node * 2 + 1, mid + 1, end); return std::max(leftQuery, rightQuery); } }; class sumSegmentTree { int n; std::vector tree, lazy; public: sumSegmentTree(int size) { n = size; tree.assign(4 * n, 0); lazy.assign(4 * n, 0); } void push(int node, int start, int end) { if (lazy[node] != 0) { // 遅延値を現在のノードに適用 tree[node] += (end - start + 1) * lazy[node]; // 子ノードに遅延値を伝播 if (start != end) { lazy[node * 2] += lazy[node]; lazy[node * 2 + 1] += lazy[node]; } // 現在のノードの遅延値をクリア lazy[node] = 0; } } void updateRange(int l, int r, long long value, int node = 1, int start = 0, int end = -1) { if (end == -1) end = n - 1; push(node, start, end); if (start > r || end < l) { // 完全に範囲外 return; } if (start >= l && end <= r) { // 完全に範囲内 lazy[node] += value; push(node, start, end); return; } // 部分的に範囲が重なる場合 int mid = (start + end) / 2; updateRange(l, r, value, node * 2, start, mid); updateRange(l, r, value, node * 2 + 1, mid + 1, end); tree[node] = tree[node * 2] + tree[node * 2 + 1]; } long long queryRange(int l, int r, int node = 1, int start = 0, int end = -1) { if (end == -1) end = n - 1; push(node, start, end); if (start > r || end < l) { // 完全に範囲外 return 0; } if (start >= l && end <= r) { // 完全に範囲内 return tree[node]; } // 部分的に範囲が重なる場合 int mid = (start + end) / 2; long long leftQuery = queryRange(l, r, node * 2, start, mid); long long rightQuery = queryRange(l, r, node * 2 + 1, mid + 1, end); return leftQuery + rightQuery; } long long lower_bound(int l, long long value, int node = 1, int start = 0, int end = -1, long long curval = 0) { if (end == -1) { end = n - 1; push(node, start, end); curval += queryRange(0, l - 1); if (tree[node] < value + curval) return n; } if (start == end) { if (tree[node] + curval < value) return start + 1; else return start; } int mid = (start + end) / 2; push(node * 2, start, mid); push(node * 2 + 1, mid + 1, end); if (tree[node * 2] + curval >= value) { return lower_bound(l, value, node * 2, start, mid, curval); } else { curval += tree[node * 2]; return lower_bound(l, value, node * 2 + 1, mid + 1, end, curval); } } }; static const long long MOD = 998244353; static const int MAXN = 1000000; // 必要に応じて大きく設定 // 階乗・階乗逆元の配列 static long long fact[MAXN+1], invFact[MAXN+1]; // 繰り返し二乗法 (a^b mod M) long long modpow(long long a, long long b, long long M) { long long ret = 1 % M; a %= M; while (b > 0) { if (b & 1) ret = (ret * a) % M; a = (a * a) % M; b >>= 1; } return ret; } // 前処理: 階乗と逆元のテーブルを作る void initFactorials() { // 階乗テーブル fact[0] = 1; for (int i = 1; i <= MAXN; i++) { fact[i] = fact[i-1] * i % MOD; } // 階乗逆元テーブル invFact[MAXN] = modpow(fact[MAXN], MOD - 2, MOD); // フェルマーの小定理で逆元を計算 for (int i = MAXN; i >= 1; i--) { invFact[i-1] = invFact[i] * i % MOD; } } // 組み合わせ数 C(n, r) long long comb(int n, int r) { if (r < 0 || r > n) return 0; return fact[n] * invFact[r] % MOD * invFact[n - r] % MOD; } vector> rlell(vector a) { vector> res; if (a.empty()) return res; res.push_back({a[0], 1}); long long n = a.size(); for (int i = 1; i < n; ++i) { if (a[i] == a[i - 1]) { res.back().second++; } else { res.push_back({a[i], 1}); } } return res; } vector> rlest(string a) { vector> res; if (a.empty()) return res; res.push_back({a[0], 1}); long long n = a.size(); for (int i = 1; i < n; ++i) { if (a[i] == a[i - 1]) { res.back().second++; } else { res.push_back({a[i], 1}); } } return res; } // vector cl = {-1, 0, 1, 0, -1}; // vector cl = {-1, 0, 1, 1, 1, 0, -1, -1, -1, 0}; int main() { ll n; cin >> n; vector> candidate; vector> def = { {1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 1, 1, 0, 1}, {1, 1, 1, 1, 0, 0, 1}, {0, 1, 1, 0, 0, 1, 1}, {1, 0, 1, 1, 0, 1, 1}, {1, 0, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 1, 1} }; auto f = [&](auto && self, vector frec, ll cur, ll cc) -> void { if (cur == 10) { bool flag = true; vector seg(7, 0); for (int i = 0; i < 10; ++i) { for (int j = 0; j < 7; ++j) { seg[j] += def[i][j] * frec[i]; } } ll use = seg[2] + seg[4]; if (use % 2 != 0) flag = false; use /= 2; if (!ckran(use - seg[6], frec[0] + 1)) flag = false; seg[0] -= use - seg[6]; seg[1] -= use - seg[6]; seg[5] -= use - seg[6]; seg[6] = use; if (!ckran(use - seg[4], frec[1] + 1)) flag = false; seg[1] -= use - seg[4]; seg[2] -= use - seg[4]; seg[5] += use - seg[4]; seg[4] = use; if (!ckran(seg[0] - use, frec[6] + 1)) flag = false; seg[0] = use; if (!ckran(use - seg[5], frec[7] + 1)) flag = false; seg[5] = use; if (!ckran(seg[3] - use, frec[9] + 1)) flag = false; seg[3] = use; if (seg[1] != use || seg[2] != use) flag = false; if (flag) candidate.push_back(frec); return; } for (int i = 0; i < 20 - cc; ++i) { self(self, frec, cur + 1, cc + i); frec[cur]++; } }; f(f, vector(10, 0), 0, 0); auto vec = lltovec(n); ll vs = vec.size(); vec = lltovec(n, 10, 18); ll ans = 2e18; ll fc = 0; vector pl(19, 1); for (int i = 1; i < 19; ++i) { pl[i] = pl[i - 1] * 10; } auto f2 = [&](auto && self, vector frec, ll cur, ll cn) -> void { if (fc < vs) return; if (cur == -1) { chmin(ans, cn); } if (cn > n || cur > fc) { for (int i = 0; i < 10; ++i) { if (frec[i] > 0) { frec[i]--; cn += pl[cur] * i; self(self, frec, cur - 1, cn); break; } } } else { if (frec[vec[cur]] > 0) { if (cur == 18) cn += pl[18]; else cn += pl[cur] * vec[cur]; frec[vec[cur]]--; self(self, frec, cur - 1, cn); if (cur == 18) cn -= pl[18]; else cn -= pl[cur] * vec[cur]; frec[vec[cur]]++; } for (int i = vec[cur] + 1; i < 10; ++i) { if (frec[i] > 0) { if (cur == 18) cn += pl[18]; else cn += pl[cur] * i; frec[i]--; self(self, frec, cur - 1, cn); break; } } } }; // for (int i = 100; i < 110; ++i) { // for (int j = 0; j < 10; ++j) { // for (int k = 0; k < candidate[i][j]; ++k) { // cout << j; // } // } // cout << endl; // } for (int i = 0; i < (int)candidate.size(); ++i) { for (int j = 0; j < 10; ++j) fc += candidate[i][j]; // if (fc <= 4) { // for (int j = 0; j < 10; ++j) { // for (int k = 0; k < candidate[i][j]; ++k) { // cout << j; // } // } // cout << endl; // } f2(f2, candidate[i], fc - 1, 0); fc = 0; } cout << ans << endl; }