// 演算法 / Algorithm: identical to the C version.
// 1) answer = f(num2) - f(num1-1), f(N) = total waviness over [0, N].
// 2) Digit DP with state (pos, last, secondLast, tight), each state returning a
//    (count, sum) pair so we sum waviness rather than merely counting numbers.
// 3) Sentinel digit 10 marks "no real digit yet" to ignore leading zeros.

#include <vector>
#include <array>
#include <cstring>
using namespace std;

class Solution {
    using ll = long long;                 // 64 位元別名 / 64-bit alias

    vector<int> dig;                       // 上界 N 的各位，最高位在前 / digits of N, MSB first
    // memo[pos][last][sec] 存 (count, sum)；用 -1 標記未計算 / memo of (count,sum)
    // pair 是把兩個值打包在一起的標準容器 / std::pair bundles two values
    ll cntMemo[16][11][11];
    ll sumMemo[16][11][11];
    bool vis[16][11][11];

    // 回傳 (count, sum) / returns {count, sum} as a pair
    pair<ll, ll> dp(int pos, int last, int sec, bool tight) {
        if (pos == (int)dig.size())        // 填完所有位 → 一個完整數字 / full number
            return {1, 0};                 // 一個數字、此處無新增波動度 / one number, +0

        // 非 tight 且已快取就直接回傳 / reuse cached free states
        if (!tight && vis[pos][last][sec])
            return {cntMemo[pos][last][sec], sumMemo[pos][last][sec]};

        int hi = tight ? dig[pos] : 9;     // 這位的上界 / upper bound for this digit
        ll tc = 0, ts = 0;                 // 累計 count 與 sum / running totals

        for (int d = 0; d <= hi; ++d) {    // range-for 不適用，這裡用一般 for 列舉數字
            int nlast, nsec;               // 下一狀態的 last/secondLast / next digits
            ll e = 0;                      // 本步是否形成峰/谷 / peak-or-valley gained

            if (last == 10) {              // 仍在前導零階段 / leading-zero phase
                if (d == 0) { nlast = 10; nsec = 10; }   // 再一個前導零 / another zero
                else        { nlast = d;  nsec = 10; }   // 第一個真實數位 / first real digit
            } else {                       // 已有真實數位 / have real digits already
                nsec = last;               // 左移：last → secondLast / shift
                nlast = d;                 // d 成為新的 last / d becomes last
                if (sec != 10) {           // 兩側都有真鄰居才判斷 / need both neighbors
                    if ((last > sec && last > d) ||      // 山峰 / peak
                        (last < sec && last < d))        // 山谷 / valley
                        e = 1;             // 為此數字 +1 波動度 / +1 waviness
                }
            }

            // 結構化綁定：把 pair 拆成兩個變數 / structured bindings unpack the pair
            auto [c, s] = dp(pos + 1, nlast, nsec, tight && (d == hi));
            tc += c;                       // 累加數字個數 / accumulate count
            ts += s + e * c;               // 子總和 + 本步每數字各加 e / add this step's gain
        }

        if (!tight) {                      // 只快取非 tight 狀態 / cache only free states
            vis[pos][last][sec] = true;
            cntMemo[pos][last][sec] = tc;
            sumMemo[pos][last][sec] = ts;
        }
        return {tc, ts};
    }

    ll f(ll N) {                           // [0, N] 的波動度總和 / total waviness over [0, N]
        if (N < 0) return 0;               // N 可能為 num1-1 = 0 或更小的防護 / guard

        dig.clear();
        vector<int> tmp;                   // 先以最低位在前收集 / collect LSB first
        if (N == 0) tmp.push_back(0);      // 0 要特別放入 / handle zero explicitly
        for (ll t = N; t > 0; t /= 10)     // 逐次取餘拆位 / peel digits with % and /
            tmp.push_back((int)(t % 10));
        dig.assign(tmp.rbegin(), tmp.rend());  // 反轉成最高位在前 / reverse to MSB first

        memset(vis, 0, sizeof(vis));       // 每次重置快取（位數會變）/ reset cache per call

        auto [c, s] = dp(0, 10, 10, true); // 起始：哨兵 last/sec、tight=true / start state
        return s;                          // 取波動度總和 / return the sum
    }

public:
    long long totalWaviness(long long num1, long long num2) {
        return f(num2) - f(num1 - 1);      // 前綴和相減取得區間結果 / prefix-sum subtraction
    }
};
