文章目录
B - Grid with Arrows(简单图论)
- 把二维平面转化成一维的点,每个位置的箭头和数字表示一条有向边
- 从入度为 0 的地方开始 dfs,再判断是不是所有点都遍历过了
- 如果没有入度为 0 的点,说明所有点都在环上,但是不一定都在同一个环上,所以随便选一个点dfs一下,看看能不能经过所有点
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e6 + 10;
const int maxn = 1e6;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, m; cin >> n >> m;
vector<string> way(n + 1);
vector<int> g(n * m + 10);
for (int i = 1; i <= n; i ++ )
{
cin >> way[i];
way[i] = " " + way[i];
}
auto getver = [&](int x, int y)
{
return (x - 1) * m + y;
};
vector<int> ind(n * m + 10);
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ )
{
int x; cin >> x;
int ver = getver(i, j);
int nv = 0;
if (way[i][j] == 'u' && i - x > 0) nv = getver(i - x, j);
else if (way[i][j] == 'd' && i + x <= n) nv = getver(i + x, j);
else if (way[i][j] == 'l' && j - x > 0) nv = getver(i, j - x);
else if (way[i][j] == 'r' && j + x <= m) nv = getver(i, j + x);
g[ver] = nv;
if (nv != 0) ind[nv] ++ ;
}
}
bool flag = false;
vector<bool> st(n * m + 1);
function<void(int)> dfs = [&](int u)
{
int nxt = g[u];
if (st[nxt] || nxt == 0) return;
st[nxt] = true;
dfs(nxt);
};
for (int i = 1; i <= n * m; i ++ )
{
if (ind[i] == 0)
{
flag = true;
st[i] = true;
dfs(i);
break;
}
}
if (flag) // 已经dfs过一次
{
for (int i = 1; i <= n * m; i ++ ) // 检查是否还有点没遍历到
{
if (!st[i])
{
cout << "No\n";
return;
}
}
cout << "Yes\n";
}
else // 点都在环上
{
st[1] = true;
dfs(1);
for (int i = 1; i <= n * m; i ++ ) // 检查是否还有点没遍历到
{
if (!st[i])
{
cout << "No\n";
return;
}
}
cout << "Yes\n";
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
C - 0689(思维 + 后缀统计)
- 从前往后枚举每个地方为起点,终点只需要看它之后有多少个数作为终点,rotate 一下和起点不一样:
- 以 0 0 0 为起点,终点可以是 6 6 6 , 8 8 8 , 9 9 9
- 以 6 6 6 为起点,终点可以是 0 0 0 , 6 6 6 , 8 8 8
- 以 8 8 8 为起点,终点可以是 0 0 0 , 6 6 6 , 9 9 9
- 以 9 9 9 为起点,终点可以是 0 0 0 , 8 8 8 , 9 9 9
- 为什么可以这么计算呢,因为如果开头结尾 rotate 一下是一样的,那就可以直接选择更短的区间进行 rotate 达到一样的效果
- 所以统计一下后缀,也就是每个数后面有多少个 0689,计算一下就行了
- 坑点是需不需要加自身呢?如果有 0 或者 8 的话,rotate 一下就是本身,所以需要加自身,另一种需要加自身的情况是同时出现了 6 和 9,因为这两个数相互 rotate 相等
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e6 + 10;
const int maxn = 1e6;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
string s; cin >> s;
int n = s.size();
s = " " + s;
vector<vector<int>> cnt(n + 2, vector<int>(4));
int ans = 0;
bool flag = false, f1 = false, f2 = false;
for (int i = n; i >= 1; i -- )
{
for (int j = 0; j < 4; j ++ )
{
cnt[i][j] = cnt[i + 1][j];
}
if (s[i] == '0')
{
flag = true;
cnt[i][0] ++ ;
ans += cnt[i][1] + cnt[i][2] + cnt[i][3];
}
else if (s[i] == '6')
{
f1 = true;
cnt[i][1] ++ ;
ans += cnt[i][0] + cnt[i][1] + cnt[i][2];
}
else if (s[i] == '8')
{
flag = true;
cnt[i][2] ++ ;
ans += cnt[i][0] + cnt[i][1] + cnt[i][3];
}
else if (s[i] == '9')
{
f2 = true;
cnt[i][3] ++ ;
ans += cnt[i][0] + cnt[i][2] + cnt[i][3];
}
}
if (f1 && f2) flag = true;
if (flag) cout << ans + 1 << '\n';
else cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
D - Pick Up(思维)
- 答案初始化为baobao直接去商场的时间
- x a , y a , x b , y b x_a,\ y_a, \ x_b,\ y_b xa, ya, xb, yb 形成的矩形中,找出距离商场最近的点 d d d,两个人先走到 d d d 再去商场和直接去商场的路径是一样的
- 如果baobao先到 d d d,那DreamGrid可以在去商场的路上带上baobao,所以答案和DreamGrid去商场的时间取最小值
- 如果DreamGrid先到 d d d,那他会先去接baobao,从出发到接到baobao的时间可以计算出来,另外加上一起去商场的时间就可以了
- 坑点是卡cin
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e5 + 10;
const int maxn = 1e6;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
double cal(int x1, int y1, int x2, int y2, double v)
{
return 1.0 * (labs(x1 - x2) + labs(y1 - y2)) / v;
}
void solve()
{
double a, b;
int xa, ya, xb, yb, xc, yc;
scanf("%Lf%Lf%lld%lld%lld%lld%lld%lld", &a, &b, &xa, &ya, &xb, &yb, &xc, &yc);
double ans = cal(xa, ya, xc, yc, a); // baobao到商场
int l = min(xa, xb), r = max(xa, xb);
int u = min(ya, yb), d = max(ya, yb);
int xd = max(l, min(r, xc)), yd = max(u, min(d, yc));
double ta = cal(xa, ya, xd, yd, a), tb = cal(xb, yb, xd, yd, b);
if (ta < tb) ans = min(ans, cal(xb, yb, xc, yc, b));
else
{
double t = cal(xa, ya, xb, yb, a + b);
double dis = labs(xa - xc) + labs(ya - yc) - t * a;
ans = min(ans, t + dis / b);
}
printf("%.8Lf\n", ans);
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
E - Turn It Off(二分)
- 直接二分,不要再无脑贪心了
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e6 + 10;
const int maxn = 1e6;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, k;
cin >> n >> k;
string s; cin >> s;
int l = 1, r = n;
auto check = [&](int mid)
{
int cnt = 0;
for (int i = 0; i < s.size(); i ++ )
{
if (s[i] == '0') continue;
cnt ++ ;
i += mid - 1;
}
if (cnt > k) return false;
else return true;
};
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << r << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
F - K-hour Clock(思维)
- 当 x + y < z x+y<z x+y<z ,不可能实现
- 当 x + y = z x+y=z x+y=z ,输出比 z z z 大的任何一个数
- 当 x + y > z x+y>z x+y>z,肯定是先从 x x x 到 k k k,再从 0 0 0 到 z z z,所以我们先把后面多的 z z z 减掉,再把前面少的 x x x 加上,这样得到的数一定是 k k k 的倍数,判断一下这个数是不是都大于 x x x 和 y y y,是的话直接输出就好了
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e6 + 10;
const int maxn = 1e6;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int x, y, z; cin >> x >> y >> z;
if (x + y < z)
{
cout << -1 << '\n';
return;
}
if (x + y == z)
{
cout << z + 1 << '\n';
return;
}
int tmp = y - z + x;
int maxx = max(x, z);
if (tmp > maxx) cout << tmp << '\n';
else cout << -1 << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
H - To the Park(构造)
- 首先 1 1 1 一定不行,然后从大到小枚举质数,如果质数的两倍大于 n n n 肯定不行
- 把质数的倍数存起来,如果在 n n n 以内的有偶数个,正好两两配对,如果奇数个,就单独把两倍的质数提出来,之后和其余没用上的偶数配对
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e5 + 10;
const int maxn = 1e6;
const int MAXN = 1e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
bool isprime[MAXN]; // isprime[i]表示i是不是素数
vector<int> prime;
int n; // 上限,即筛出<=n的素数
int cnt; // 已经筛出的素数个数
void euler()
{
memset(isprime, true, sizeof(isprime)); // 先全部标记为素数
isprime[1] = false; // 1不是素数
prime.push_back(0);
for(int i = 2; i <= 1e5; ++i) // i从2循环到n(外层循环)
{
if(isprime[i])
{
prime.push_back(i);
cnt ++ ;
}
// 如果i没有被前面的数筛掉,则i是素数
for(int j = 1; j <= cnt && i * prime[j] <= 1e5; ++j)
// 筛掉i的素数倍,即i的prime[j]倍
// j循环枚举现在已经筛出的素数(内层循环)
{
isprime[i * prime[j]] = false;
// 倍数标记为合数,也就是i用prime[j]把i * prime[j]筛掉了
if(i % prime[j] == 0) break;
// 最神奇的一句话,如果i整除prime[j],退出循环
// 这样可以保证线性的时间复杂度
}
}
}
void solve()
{
int n; cin >> n;
vector<bool> st(n + 1); // 哪些数已经被用过了
vector<int> noused;
vector<PII> ans;
for (int i = cnt; i > 1; i -- )
{
int num = prime[i];
if (num * 2 > n) continue;
vector<int> tmp;
int idx = 2;
tmp.push_back(num);
while (num * idx <= n)
{
if (!st[num * idx])
{
st[num * idx] = true;
tmp.push_back(num * idx);
}
idx ++ ;
}
if (tmp.size() & 1)
{
noused.push_back(2 * num);
ans.push_back({tmp[0], tmp[2]});
for (int i = 3; i < tmp.size(); i += 2 ) ans.push_back({tmp[i], tmp[i + 1]});
}
else
{
for (int i = 0; i < tmp.size(); i += 2) ans.push_back({tmp[i], tmp[i + 1]});
}
}
for (int i = 2; i <= n; i += 2) if (!st[i]) noused.push_back(i);
for (int i = 0; i < (int)(noused.size()) - 1; i += 2) ans.push_back({noused[i], noused[i + 1]});
cout << ans.size() << ' ';
for (auto t : ans) cout << t.first << ' ' << t.second << ' ';
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
euler();
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
I - Unrooted Trie(dfs序 + 差分)
-
有两种情况,这棵树就一定不是合法的字典树:
- 一个结点连接了大于 2 个相同的字母
- 一个结点连接了大于 1 种出现两次的字母
-
如果不处于以上两种情况,我们只需要看那些地方不能当做根,做个标记,没做标记的地方统计答案
-
如果一个结点连接的所有字母都只出现了一次,那对答案没有影响,如果有一个字母出现了两次,根结点必然在这两个点所在的子树里,对整个子树打标记,想到可以用 dfs 序
-
先随便选个点开始 dfs 一下求出 dfs 序,然后遍历所有点,遍历到的点记为 u u u,相邻的字母相同的点记作 v 1 v_1 v1 和 v 2 v_2 v2
- 如果 d f n [ u ] < d f n [ v 1 ] dfn[u]<dfn[v_1] dfn[u]<dfn[v1] 且 d f n [ u ] < d f n [ v 2 ] dfn[u]<dfn[v_2] dfn[u]<dfn[v2],说明 u u u 是 v 1 v_1 v1 和 v 2 v_2 v2 的父结点,那除了两个子树的其余部分都不能作为根结点,就先把全体打上+1标记,两个子树打上-1标记
- 否则, d f n [ u ] dfn[u] dfn[u] 一定处于 d f n [ v 1 ] dfn[v_1] dfn[v1] 和 d f n [ v 2 ] dfn[v_2] dfn[v2] 之间,不能作为根结点的部分就是 u u u 的子树除去 v 1 v_1 v1 或者 v 2 v_2 v2 的子树部分
-
差分打标记就行
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e5 + 10;
const int maxn = 1e6;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n; cin >> n;
vector<vector<PII>> g(n + 1);
for (int i = 0; i < n - 1; i ++ )
{
int u, v;
char c;
cin >> u >> v >> c;
g[u].push_back({v, c - 'a'});
g[v].push_back({u, c - 'a'});
}
int timestamp = 0;
vector<int> dfn1(n + 1), dfn2(n + 1);
function<void(int, int)> dfs = [&](int u, int fa)
{
dfn1[u] = ++ timestamp;
for (int i = 0; i < g[u].size(); i ++ )
{
int j = g[u][i].first, c = g[u][i].second;
if (j == fa) continue;
dfs(j, u);
}
dfn2[u] = timestamp;
};
dfs(1, -1);
vector<int> diff(n + 2);
for (int i = 1; i <= n; i ++ )
{
vector<vector<int>> cnt(26);
int flag = -1;
for (int j = 0; j < g[i].size(); j ++ )
{
int v = g[i][j].first, c = g[i][j].second;
cnt[c].push_back(v);
if (cnt[c].size() > 2)
{
cout << 0 << '\n';
return;
}
else if (cnt[c].size() == 2)
{
if (flag != -1)
{
cout << 0 << '\n';
return;
}
else flag = c;
}
}
if (flag == -1) continue;
int v1 = cnt[flag][0], v2 = cnt[flag][1];
if (dfn1[v1] > dfn1[v2]) swap(v1, v2);
if (dfn1[i] < dfn1[v1] && dfn1[i] < dfn1[v2])
{
diff[1] ++ , diff[n + 1] ++ ;
diff[dfn1[v1]] -- , diff[dfn2[v1] + 1] ++ ;
diff[dfn1[v2]] -- , diff[dfn2[v2] + 1] ++ ;
}
else
{
diff[dfn1[i]] ++ , diff[dfn2[i] + 1] -- ;
diff[dfn1[v2]] -- , diff[dfn2[v2] + 1] ++ ;
}
}
int ans = 0;
for (int i = 1; i <= n; i ++ )
{
diff[i] += diff[i - 1];
if (diff[i] == 0) ans ++ ;
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
J - Coolbits(位运算)
- 按位考虑答案应该是很常见的思路了
- 从高位往低位考虑,假设当前在考虑第
i
i
i 位,用
r
e
s
[
j
]
res[j]
res[j] 表示第
j
j
j 个区间从最高位到第
i
+
1
i+1
i+1 位选的数:
- 第 i i i 位为 1 1 1,条件是对于所有的 j j j, [ r e s j + 2 i , r e s j + 2 i + 1 − 1 ] [res_j+2^i,\ res_j+2^{i+1}-1] [resj+2i, resj+2i+1−1] 必须与 [ l j , r j ] [l_j,\ r_j] [lj, rj] 有交集,对于第 j j j 个数,让 r e s [ j ] res[j] res[j] 加上 2 i 2^i 2i 即可
- 否则第
i
i
i 位为
0
0
0:
- 如果 [ r e s j + 2 i , r e s j + 2 i + 1 − 1 ] [res_j+2^i,\ res_j+2^{i+1}-1] [resj+2i, resj+2i+1−1] 和 [ l j , r j ] [l_j,\ r_j] [lj, rj] 没有交集,第 j j j 个数的第 i i i 位取 0 0 0, r e s [ j ] res[j] res[j] 不做改变
- 如果有交集,就看一下 r e s j + 2 i − 1 res_j+2^i-1 resj+2i−1 在不在 [ l j , r j ] [l_j,\ r_j] [lj, rj],如果在的话,直接第 i i i 位填 0 0 0,后面全填 1 1 1 就可以了(第 j j j 个数之后都不需要再考虑了),如果不在这一位就只能填 1 1 1
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e5 + 10;
const int maxn = 1e6;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n; cin >> n;
vector<PII> a(n + 1);
vector<int> res(n + 1);
vector<bool> st(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i].first >> a[i].second;
int ans = 0;
for (int i = 31; i >= 0; i -- ) // 目前考虑到哪一位了
{
bool flag = true; // 当前位能不能填1
for (int j = 1; j <= n; j ++ )
{
if (st[j]) continue;
int tmpl = res[j] + (1ll << i), tmpr = res[j] + (1ll << (i + 1)) - 1;
int l = a[j].first, r = a[j].second;
if (r < tmpl || l > tmpr)
{
flag = false;
break;
}
}
if (flag) // 当前位取1
{
for (int j = 1; j <= n; j ++ )
{
if (st[j]) continue;
res[j] += (1 << i);
}
ans += (1ll << i);
}
else // 当前位取0
{
for (int j = 1; j <= n; j ++ )
{
if (st[j]) continue;
int tmpl = res[j] + (1ll << i), tmpr = res[j] + (1ll << (i + 1)) - 1;
int l = a[j].first, r = a[j].second;
if (r >= tmpl && l <= tmpr)
{
int tmp = res[j] + (1ll << i) - 1;
if (tmp >= l && tmp <= r)
{
res[j] += (1ll << i) - 1;
st[j] = true;
}
else res[j] += (1ll << i);
}
}
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
K - Escape Plan(Dijkstra变种)
- 从终点开始跑最短路,但是只有堆顶出现 d [ u ] d[u] d[u] 次 u u u 之后才能更新 d i s t [ u ] dist[u] dist[u]
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e5 + 10;
const int maxn = 1e6;
const int MAXN = 1e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, m, k;
cin >> n >> m >> k;
vector<int> dist(n + 1, INF), e(k + 1);
priority_queue<PII, vector<PII>, greater<PII>> pq;
for (int i = 1; i <= k; i ++ )
{
int x; cin >> x;
e[i] = x;
pq.push({0, x});
}
vector<int> d(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> d[i];
for (int i = 1; i <= k; i ++ ) d[e[i]] = 0;
vector<vector<PII>> g(n + 1);
for (int i = 1; i <= m; i ++ )
{
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
}
while (pq.size())
{
auto t = pq.top();
pq.pop();
int dd = t.first, ver = t.second;
if (d[ver] <= 0)
{
if (dist[ver] > dd) dist[ver] = dd;
else continue;
}
else
{
d[ver] -- ;
continue;
}
for (int i = 0; i < g[ver].size(); i ++ )
{
int j = g[ver][i].first, w = g[ver][i].second;
if (dist[j] > dd + w)
{
pq.push({dd + w, j});
}
}
}
if (dist[1] == INF) cout << -1 << '\n';
else cout << dist[1] << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
L - Digit Product(签到)
- 每十个数必会出现一个 0,所以直接遍历就行,碰到 0 直接退出
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e6 + 10;
const int maxn = 1e6;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int l, r;
cin >> l >> r;
int ans = 1;
for (int i = l; i <= r; i ++ )
{
string s = to_string(i);
for (auto t : s)
{
int num = t - '0';
if (num == 0)
{
cout << 0 << '\n';
return;
}
ans = (ans * num) % mod;
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}