#include #include using namespace std; using ll = long long; using mint = atcoder::modint998244353; static constexpr int LIM_M = 1000000; static constexpr int LIM_K = 10; vector> acc_jordan; void prev() { // spf[i] := i の最小素因数 vector spf(LIM_M + 1, 0); vector primes; for (int i = 2; i <= LIM_M; i++) { if (spf[i] == 0) { spf[i] = i; primes.push_back(i); } for (int p: primes) { ll v = (ll)i * p; if (v > LIM_M || p > spf[i]) break; spf[v] = p; } } // jordan[k][n] := Jordan のトーシェント関数 J_k(n) vector jordan(LIM_K + 1, vector(LIM_M + 1, mint(1))); for (int k = 1; k <= LIM_K; k++) { for (int n = 2; n <= LIM_M; n++) { int m = n / spf[n]; if (m % spf[n] == 0) { jordan[k][n] = jordan[k][m] * mint(spf[n]).pow(k); } else { jordan[k][n] = jordan[k][m] * (mint(spf[n]).pow(k) - 1); } } } // Jordan のトーシェント関数の累積和 acc_jordan = vector(LIM_K + 1, vector(LIM_M + 2, mint(0))); for (int k = 1; k <= LIM_K; k++) { for (int n = 0; n <= LIM_M; n++) { acc_jordan[k][n + 1] = acc_jordan[k][n] + jordan[k][n]; } } } void solve() { int N, M, K; cin >> N >> M >> K; mint ans = 0; int l = 1; while (l <= M) { int q = M / l; int r = M / q; mint sum_j = acc_jordan[K][r + 1] - acc_jordan[K][l]; ans += sum_j * mint(q).pow(N); l = r + 1; } cout << ans.val() << '\n'; } int main() { int T; cin >> T; prev(); while (T--) solve(); return 0; }