#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using ll=long long; #include using mint=atcoder::modint998244353; ostream& operator<<(ostream& os,const mint& x){ os<>(istream& is,mint& x){ int t; is>>t; x=t; return is; } template ostream& operator<<(ostream& os,const pair& p); template istream& operator>>(istream& is,pair& p); template ostream& operator<<(ostream& os,const array& arr); template istream& operator>>(istream& is,array& arr); template ostream& operator<<(ostream& os,const vector& vec); template istream& operator>>(istream& is,vector& vec); template ostream& operator<<(ostream& os,const pair& p){ os< istream& operator>>(istream& is,pair& p){ is>>p.first>>p.second; return is; } template ostream& operator<<(ostream& os,const array& arr){ for(int i=0;i istream& operator>>(istream& is,array& arr){ for(int i=0;i>arr[i]; return is; } template ostream& operator<<(ostream& os,const vector& vec){ for(int i=0;i<(int)vec.size();i++)os< istream& operator>>(istream& is,vector& vec){ for(int i=0;i<(int)vec.size();i++)is>>vec[i]; return is; } template void input_vec(Vecs&... vs) { const auto n = get<0>(tie(vs...)).size(); for (size_t i = 0; i < n; ++i) ((cin >> vs[i]), ...); } template vector make_unique(vector vec){ ranges::sort(vec); vec.erase(unique(vec.begin(),vec.end()),vec.end()); return vec; } template pair,vector> make_rank(const vector& vec, Comp comp = {}, Proj proj = {}) { int n = vec.size(); vector argsort(n); iota(argsort.begin(), argsort.end(), 0); ranges::stable_sort(argsort, comp, [&](int i) -> decltype(auto) { return invoke(proj, vec[i]); }); vector rank(n); for(int i=0;i; using vvl=vector>; using vvvl=vector>>; using vi=vector; using vvi=vector>; using vvvi=vector>>; struct Combination{ Combination(int n){ init(n); } Combination(){}; private: int n; vector _fact,_factinv; void init(int n){ this->n=n; _fact.resize(n+1,1);_factinv.resize(n+1,1); for(int i=0;i=0;i--)_factinv[i]=_factinv[i+1]*(i+1); } public: mint fact(int x){ return _fact[x]; } mint factinv(int x){ return _factinv[x]; } mint C(int x,int y){ assert(0<=x&&x<=n&&0<=y); if(x(a-1,b) void down_binomsum_a(int& a,int& b,mint& c){ c-=comb.C(b,a-1); } //(a,b)->(a+1,b) void up_binomsum_a(int& a,int& b,mint& c){ c+=comb.C(b,a); } //(a,b)->(a,b-1) void down_binomsum_b(int& a,int& b,mint& c){ if(a!=0) c=(c+comb.C(b-1,a-1))*comb.frac(1,2); } //(a,b)->(a,b+1) void up_binomsum_b(int& a,int& b,mint& c){ if(a!=0) c=2*c-comb.C(b,a-1); } int main(){ cin.tie(nullptr); ios::sync_with_stdio(false); cout<>n>>m; ll N=max(n,m); comb=Combination(N+1); vl primes,lpf(N+1,-1),cnt(N+1); vector f(N+1); f[1]=1; for(ll i=2;i<=N;i++){ if(lpf[i]==-1){ lpf[i]=i; primes.push_back(i); f[i]=-comb.frac(i-1,i); cnt[i]=1; } for(ll p:primes){ if(p>lpf[i]||p*i>N)break; ll nxt=i*p; lpf[nxt]=p; if(lpf[i]==p){ cnt[nxt]=cnt[i]+1; f[nxt]=f[i]*comb.frac(1,lpf[i]); } else{ cnt[nxt]=1; f[nxt]=f[i]*f[p]; } } } mint ans=0; for(ll i=1;i<=N;i++){ mint a=(n/i)*(n/i+1)/2; mint b=(m/i)*(m/i+1)/2; ans+=f[i]*a*b*i*i; } cout<