#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 mint inv2; mint f(long long n, long long p) { long long c = n / p; mint x = p; mint y = p * c; return (x + y) * c * inv2; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); long long n, m; cin >> n >> m; inv2 = mint(2).inv(); auto mu = kwm_t::math::mobius_table(10000007); mint ans = 0; rrep2(i, 1, 10000007) { auto x = f(n, i); auto y = f(m, i); mint z = x * y; ans += mu[i] * z; } cout << ans.val() << endl; return 0; }