<p>You are given an array <code>nums</code> that consists of non-negative integers. Let us define <code>rev(x)</code> as the reverse of the non-negative integer <code>x</code>. For example, <code>rev(123) = 321</code>, and <code>rev(120) = 21</code>. A pair of indices <code>(i, j)</code> is <strong>nice</strong> if it satisfies all of the following conditions:</p>

<ul>
	<li><code>0 &lt;= i &lt; j &lt; nums.length</code></li>
	<li><code>nums[i] + rev(nums[j]) == nums[j] + rev(nums[i])</code></li>
</ul>

<p>Return <em>the number of nice pairs of indices</em>. Since that number can be too large, return it <strong>modulo</strong> <code>10<sup>9</sup> + 7</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> nums = [42,11,1,97]
<strong>Output:</strong> 2
<strong>Explanation:</strong> The two pairs are:
 - (0,3) : 42 + rev(97) = 42 + 79 = 121, 97 + rev(42) = 97 + 24 = 121.
 - (1,2) : 11 + rev(1) = 11 + 1 = 12, 1 + rev(11) = 1 + 11 = 12.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> nums = [13,10,35,24,76]
<strong>Output:</strong> 4
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
	<li><code>0 &lt;= nums[i] &lt;= 10<sup>9</sup></code></li>
</ul>

template <class K, class T, K maxsize, unsigned char bucket_bits = 1>
class static_flat_hash_map {
public:
    typedef pair<K, T> value_type;

    static constexpr K ZERO_VAL = sizeof(K) == 1 ? CHAR_MIN :
        sizeof(K) == 2 ? SHRT_MIN : sizeof(K) == 4 ? INT_MIN : LONG_LONG_MIN;

    static bool equal(K km, K ku) {
        return km && (km == ZERO_VAL ? 0 : km) == ku;
    }

    static bool equal_or_free(K km, K ku) {
        return !km || (km == ZERO_VAL ? 0 : km) == ku;
    }

private:
    static constexpr size_t getcap(size_t size) __attribute__((always_inline)) {
        return 1ull << 64u - __builtin_clzll(size - 1);
    }

    static constexpr size_t cap = getcap(maxsize);
    value_type storage[cap];
    size_t limit;

    static size_t hash(const K k) __attribute__((always_inline)) {
        return size_t(k) * 31;
    }

    value_type *locate(K k) {
        const size_t h = (hash(k) << bucket_bits) & (limit - 1);
        size_t i = h;
        while (i < limit && !equal_or_free(storage[i].first, k)) i++;
        if (i >= limit) i = 0;
        while (i < h && !equal_or_free(storage[i].first, k)) i++;
        return storage + i;
    }

public:

    class iterator {
    private:
        value_type *curr, *const end;

    public:
        iterator(value_type *start, size_t ofs, size_t cap) __attribute__((always_inline)): curr(start + ofs), end(start + cap) {}

        iterator(value_type *curr, value_type *end) __attribute__((always_inline)): curr(curr), end(end) {}

        value_type *operator->() __attribute__((always_inline)) {
            return curr;
        }

        value_type &operator*() __attribute__((always_inline)) {
            return *curr;
        }

        iterator &operator++ () __attribute__((always_inline)) {
            while (curr < end && !curr->first) curr++;
            return *this;
        }

        iterator operator++ (int) __attribute__((always_inline)) {
            return ++*this;
        }

        bool operator== (iterator another) {
            return curr == another.curr;
        }
    };

    static_flat_hash_map(): storage{}, limit(cap) {}

    iterator find(K k) __attribute__((always_inline)) {
        value_type *p = locate(k);
        return iterator(storage, p - storage, limit);
    }

    iterator insert(iterator p, const value_type &v) __attribute__((always_inline)) {
        p->first = v.first ? v.first : ZERO_VAL;
        p->second = v.second;
        return p;
    }

    T &operator[](const K k) __attribute__((always_inline)) {
        auto it = find(k);
        return it->first ? it->second : insert(it, pair(k, 0))->second;
    }

    iterator begin() __attribute__((always_inline)) {
        return iterator(storage, 0, limit);
    }

    iterator end() __attribute__((always_inline)) {
        return iterator(storage, limit, limit);
    }

    void resize(const size_t size) __attribute__((always_inline)) {
        limit = getcap(size);
    }
};

class Solution {
private:
    typedef long long i64_t;
    typedef unsigned long long u64_t;
    static constexpr unsigned MAXN = 100000u, MAXC = MAXN / 4u, MINC = 16u;
    static constexpr unsigned MOD = 1000000007u;
    typedef static_flat_hash_map<int, unsigned, MAXC> map_t;
    static map_t diffs;

    static unsigned revdigits(unsigned v) {
        unsigned r = 0;
        while (v) {
            const unsigned d = v / 10;
            r = (r - d) * 10 + v;
            v = d;
        }
        return r;
    }

public:
    int countNicePairs(const vector<int>& nums) {
        const unsigned n = nums.size();
        const unsigned cap = n >= MINC * 1024u && nums[0] == nums[MINC/4u] && nums[0] == nums[MINC/2u] && nums[0] == nums[MINC-1u] ? n / 1024u : n;
        diffs.resize(max(MINC, min(cap, MAXC)));
        for (const int v : nums) {
            const int rev = revdigits(v);
            diffs[v - rev]++;
        }
        u64_t total = 0;
        for (auto &p : diffs) {
            total += (u64_t)p.second * (p.second - 1u) / 2;
            p.first = 0; // very dirty, right
            p.second = 0;
        }
        return total % MOD;
    }
};

Solution::map_t Solution::diffs;
57900