#include <bits/stdc++.h>
using namespace std;
//写中文注释来环节编码的压力
struct info {
int n;
int a;
};
vector<info> ans;
int digitsum(int x) {
int sum = 0;
string t = to_string(x);
for (int i = 0; i < t.size(); i++) {
sum += (t[i] - '0');
}
//函数输出返回值
return sum;
}
int gcd(int x, int y) {
if (y == 0)return x;
else gcd(y, x % y);
}
bool is_prime(int x) {
if (x <= 2)return false;//根据题目的要求因为必须要要大于2,一般只要小于等于1
for (int i = 2, z = sqrt(x); i <= z; i++) {
if (x % i == 0)return false;
}
return true;
}
bool cmp(info x, info y) {
if (x.n != y.n) {
return x.n < y.n;
}
else if (x.a != y.a) {
return x.a < y.a;
}
}
int num_len(int x) {
if(x!=0){
int count = 0;
while (x != 0) {
x = x / 10;
count++;
}
return count;
}
else {
return 1;
}
}
unordered_map<int, int> pow10;//注意没思路的时候要多些中文注释,第一个int是次幂,第二个是具体的值
void pow_table() {
for (int i = 0; i <= 9; i++) {
pow10[i] = pow(10, i);
}
}
int main()
{
#ifndef ONLINE_JUDGE
FILE* s;
freopen_s(&s, "in.txt", "r", stdin);
#endif // !ONLINE_JUDGE
int n;
cin >> n;
int k, m;
pow_table();
for (int i = 0; i < n; i++) {
//在处理一个case的情况下就是去清除最后的答案数组
ans.clear();
cin >> k >> m;
if (k * 9 >= m) {
int begin = pow(10, k - 1);
int end = pow(10, k) - 1;
int max = pow(10, k);
for (int j = begin,count=0; j <= end; j++, count++) {
//if (max - pow(10, num_len(count)) + j % (int)(pow(10, num_len(count))) >= m) {
if (max - pow10[num_len(count)] + j % pow10[num_len(count)] >= m) {
if (digitsum(j) == m) {
int n = digitsum(j + 1);
//如果判断出来是真的满足条件的话就加入
if (is_prime(gcd(n, m))) {
ans.push_back({ n,j });
}
else {
continue;
}
}
else {
continue;
}
}
}
}
sort(ans.begin(), ans.end(),cmp);
printf("Case %d\n", i + 1);
if (ans.size() == 0) {
printf("No Solution\n");
}
else {
//按照一行行的方式进行输出,输出排序以后的ans数组里面的内容
for (int i = 0; i < ans.size(); i++) {
printf("%d %d\n",ans[i].n,ans[i].a);
}
}
}
return 0;
}