#nullable enable #region var (_input, _iter) = (Array.Empty(), 0); T I() where T : IParsable { while (_iter >= _input.Length) (_input, _iter) = (Console.ReadLine()!.Trim().Split(' '), 0); return T.Parse(_input[_iter++], null); } #endregion const long Mod = 1000000007; var ns = I(); // var n = int.Parse(new string([..ns.Reverse()])); var n = int.Parse(ns); var f = new Dictionary<(long, long, bool), (Int128, Int128)>(); (Int128, Int128) F(long x, long j, bool z) { if (j <= 1 && x < 10) return (x * (x + 1) / 2, x + 1); var key = (x, j, z); if (f.TryGetValue(key, out var cv)) return cv; Int128 v = 0; Int128 c = 0; var d = x / j; if (d > 0) { var (nv, nc) = F(j - 1, j / 10, z); if (z) v += nv * 10; else v += nv; c += nc; } for (var i = 1; i < d; i++) { var (nv, nc) = F(j - 1, j / 10, true); v += nv * 10 + nc * i; c += nc; } { var nz = z || d > 0; var (nv, nc) = F(x - j * d, j / 10, nz); if (nz) v += nv * 10 + nc * d; else v += nv; c += nc; } return f[key] = (v % Mod, c % Mod); } long T(long x) { var res = 1L; while (x >= 10) (x, res) = (x / 10, res * 10); return res; } var ans = new List(); for (var i = 0; i < n; i++) { var ls = I(); var rs = I(); // var l = long.Parse(new string([..ls.Reverse()])); // var r = long.Parse(new string([..rs.Reverse()])); var l = long.Parse(ls); var r = long.Parse(rs); var t = T(r); var rns = F(r, t, false).Item1; var lns = F(l - 1, t, false).Item1; var qns = (rns - lns + Mod) % Mod; // var sns = new string([..qns.ToString().Reverse()]); var sns = qns.ToString(); ans.Add(long.Parse(sns)); // var dbg = 0L; // for (var j = 0; j <= r; j++) // { // var rev = j.ToString().Reverse(); // dbg += long.Parse(new string([..rev])); // } // Console.WriteLine(dbg); } Console.WriteLine(string.Join(Environment.NewLine, ans));