#include #include using namespace std; using namespace atcoder; // using mint = modint1000000007; // const int mod = 1000000007; using mint = modint998244353; const int mod = 998244353; // const int INF = 1e9; // const long long LINF = 1e18; #define rep(i, n) for (int i = 0; i < (n); ++i) #define rep2(i, l, r) for (int i = (l); i < (r); ++i) #define rrep(i, n) for (int i = (n)-1; i >= 0; --i) #define rrep2(i, l, r) for (int i = (r)-1; i >= (l); --i) #define all(x) (x).begin(), (x).end() #define allR(x) (x).rbegin(), (x).rend() #define P pair template inline bool chmax(A& a, const B& b) { if (a < b) { a = b; return true; } return false; } template inline bool chmin(A& a, const B& b) { if (a > b) { a = b; return true; } return false; } #ifndef KWM_T_MATH_MOBIUS_HPP #define KWM_T_MATH_MOBIUS_HPP #include namespace kwm_t::math { /** * @brief 1 以上 n 以下の Möbius 関数の値を求める * * μ(1) = 1 * μ(n) = 0 : n が平方因子を持つ * μ(n) = (-1)^k : 相異なる素因数を k 個持つ * * 計算量: * O(n log log n) * * 空間計算量: * O(n) * * @param n * Möbius 関数を求める最大値 * * 制約 / 注意: * - 戻り値の i 番目が μ(i) * - μ(0) は 0 * * 使用例: * auto mu = kwm_t::math::mobius_table(n); * * verified: * https://atcoder.jp/contests/awc0150/submissions/78988183 */ std::vector mobius_table(int n) { std::vector mu(n + 1, 1); std::vector composite(n + 1); mu[0] = 0; for (int p = 2; p <= n; ++p) { if (composite[p]) continue; for (int i = p; i <= n; i += p) { composite[i] = true; mu[i] *= -1; } for (long long i = 1LL * p * p; i <= n; i += 1LL * p * p) { mu[i] = 0; } } return mu; } } // namespace kwm_t::math #endif // KWM_T_MATH_MOBIUS_HPP int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); long long n, m; cin >> n >> m; const int lim = 30000007; auto mt = kwm_t::math::mobius_table(lim); mint inv2 = mint(2).inv(); auto s = [&](long long x) { return mint(x) * (x + 1) * inv2; }; mint ans = 0; rep2(i, 1, lim) { mint add = (mint)i*mt[i]; add *= s(n / i); add *= s(m / i); ans += add; } cout << ans.val() << endl; return 0; }