#include #include using namespace std; using mint = atcoder::modint998244353; constexpr int LIMIT = 10'000'000 + 1; vector prime_count(LIMIT, 0); vector good_prime_count(LIMIT, 0); void init() { vector is_prime(LIMIT, true); is_prime[0] = is_prime[1] = false; for (int i = 2; i < LIMIT; i++) { if (not is_prime[i]) { continue; } for (int j = 2 * i; j < LIMIT; j += i) { is_prime[j] = false; } } for (int p = 1; p < LIMIT; p++) { prime_count[p] = prime_count[p - 1]; good_prime_count[p] = good_prime_count[p - 1]; if (is_prime[p]) { prime_count[p] += 1; } int q = p ^ 2; if (p > q and is_prime[p] and is_prime[q]) { good_prime_count[p] += 2; } } } vector> mul(const vector> A, const vector> B) { int ha = A.size(), wa = A[0].size(); int wb = B[0].size(); vector res(ha, vector(wb, 0)); for (int i = 0; i < ha; i++) { for (int j = 0; j < wb; j++) { for (int k = 0; k < wa; k++) { res[i][j] += A[i][k] * B[k][j]; } } } return res; } vector> pow(const vector> A, const uint e) { int n = A.size(); vector res(n, vector(n, mint(0))); for (int i = 0; i < n; i++) { res[i][i] = mint(1); } for (int i = bit_width(e) - 1; i >= 0; i--) { res = mul(res, res); if (((e >> i) & 1) == 1) { res = mul(res, A); } } return res; } void solve() { int N, M; cin >> N >> M; if (N == 1) { cout << prime_count[M] << '\n'; return; } int c = good_prime_count[M]; vector vec(2, vector(1)); vec[0][0] = 1; vec[1][0] = c; vector matrix(2, vector(2)); matrix[0][0] = 0, matrix[0][1] = 1; matrix[1][0] = c, matrix[1][1] = 1; vector res = mul(pow(matrix, N - 1), vec); mint ans = res[0][0] + res[1][0]; cout << ans.val() << '\n'; } int main() { cin.tie(nullptr); ios::sync_with_stdio(false); init(); int T; cin >> T; for (int i = 0; i < T; i++) { solve(); } }