#include using namespace atcoder; using mint = modint1000000007; using mint2 = modint998244353; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using ll = long long; #define FOR(i, a, b) for(ll i=(a); i<(b);i++) #define REP(i, n) for(ll i=0; i<(n);i++) #define ROF(i, a, b) for(ll i=(ll(b)-1); i>=(a);i--) #define PER(i, n) for(ll i=ll(n)-1; i>=0;i--) using VL = vector; using VVL = vector>; using VP = vector< pair >; using VVP = vector>>; #define all(i) begin(i),end(i) #define SORT(i) sort(all(i)) #define EXISTBIT(x,i) (((x>>i) & 1) != 0) #define MP(a,b) make_pair(a,b) template vector read(size_t n) { vector ts(n); for (size_t i = 0; i < n; i++) cin >> ts[i]; return ts; } template void read_tuple_impl(TV&) {} template void read_tuple_impl(TV& ts) { get(ts).emplace_back(*(istream_iterator(cin))); read_tuple_impl(ts); } template decltype(auto) read_tuple(size_t n) { tuple...> ts; for (size_t i = 0; i < n; i++) read_tuple_impl(ts); return ts; } template T det2(array ar) { return ar[0] * ar[3] - ar[1] * ar[2]; } template T det3(array ar) { return ar[0] * ar[4] * ar[8] + ar[1] * ar[5] * ar[6] + ar[2] * ar[3] * ar[7] - ar[0] * ar[5] * ar[7] - ar[1] * ar[3] * ar[8] - ar[2] * ar[4] * ar[6]; } template bool chmax(T& tar, T src) { return tar < src ? tar = src, true : false; } template bool chmin(T& tar, T src) { return tar > src ? tar = src, true : false; } template void inc(vector& ar) { for (auto& v : ar) v++; } template void dec(vector& ar) { for (auto& v : ar) v--; } template vector> id_sort(vector& a) { vector> res(a.size()); for (int i = 0; i < a.size(); i++)res[i] = MP(a[i], i); SORT(res); return res; } using val = ll; using func = ll; val op(val a, val b) { return min(a, b); } val e() { return (1LL << 60); } //val mp(func f, val a) { return MP(a.first + f * a.second, a.second); } //func comp(func f, func g) { return f + g; } //func id() { return 0; } // Rook ll dxr[4] = { 1,0,-1,0 }; ll dyr[4] = { 0,1,0,-1 }; // Bishop ll dxb[4] = { -1,-1,1,1 }; ll dyb[4] = { -1,1,-1,1 }; // queen ll dxq[8] = { 0,-1,-1,-1,0,1,1,1 }; ll dyq[8] = { -1,-1,0,1,1,1,0,-1 }; void solve() { ll n,m; cin >> n >> m; ll n0 = max(n, m); VL p(n0 + 1); VL a(n0 + 1, 1); p[0] = p[1] = 1; FOR(v, 1, n0 + 1) { if (p[v]) { continue; } a[v] *= -1; ll vv = v * 2; while (vv <= n0) { if (vv % (v * v) == 0) { a[vv] = 0; } else { a[vv] *= -1; } p[vv] = 1; vv += v; } } ll ans = 0; //ll v = 1; //while(v<=n0) { // ll nx = n / v; // ll mx = m / v; // ll vv = n0+1; // if (nx > 1) // chmin(vv, n / (nx - 1)); // if (mx > 1)chmin(vv, m / (mx - 1)); // if (v == vv)vv++; // ll xx = max(nx, mx); // mint2 add = 0; // FOR(v2, 1, xx + 1) { // mint2 s0 = (v2 + nx / v2 * v2) * (nx / v2) / 2; // mint2 s1 = (v2 + mx / v2 * v2) * (mx / v2) / 2; // add += a[v2] * s0 * s1 * v; // } // if (vv < v) { // double aa = 0; // } // ans += add * (vv - v); // v = vv; //} // ええ~~~だって普通に上とほぼ同じやん??? ll mod = 998244353; vector s(n0+1); FOR(i, 1, n0 + 1) { ll s0 = (1 + n / i) * (n / i) / 2 % mod; ll s1 = (1 + m / i) * (m / i) / 2 % mod; s[i] = s0 * s1%mod; } FOR(v, 1, n0 + 1) { ll vv = v; ll c = 1; while (vv <= n0) { ans += (s[vv] * a[c] * vv)%mod*c%mod; if (ans < 0)ans += mod; if (ans >= mod)ans -= mod; vv += v; c++; } } //FOR(v, 1, n0 + 1) { // ll nx = n / v; // ll mx = m / v; // //if (memo.contains(nx*1000000000+mx)) { // // ans += memo[nx * 1000000000 + mx]; // // continue; // //} // ll xx = min(nx, mx); // mint2 add = 0; // FOR(v2, 1, xx + 1) { // ll np = nx / v2; // ll mp = mx / v2; // mint2 s0 = mint2(v2 + np * v2) * np * half; // mint2 s1 = mint2(v2 + mp * v2) * mp * half; // add += a[v2] * s0 * s1 * v; // } // memo[nx * 1000000000 + mx] = add; // ans += add; //} cout << ans; } int main() { ll t = 1; //cin >> t; while (t--) { solve(); } return 0; }