#include using namespace std; //高速化 struct ponjuice{ponjuice(){cin.tie(0);ios::sync_with_stdio(0);cout<using vc = vector; templateusing vvc = vc>; templateusing vvvc = vvc>; using vi = vc; using vvi = vvc; using vvvi = vvvc; using vl = vc; using vvl = vvc; using vvvl = vvvc; using pi = pair; using pl = pair; using ull = unsigned ll; templateusing priq = priority_queue; templateusing priqg = priority_queue, greater>; // for文 #define overload4(a, b, c, d, e, ...) e #define rep1(n) for(ll i = 0; i < n; i++) #define rep2(i, n) for(ll i = 0; i < n; i++) #define rep3(i, a, b) for(ll i = a; i < b; i++) #define rep4(i, a, b, step) for(ll i = a; i < b; i+= step) #define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__) #define per1(n) for(ll i = n-1; i >= 0; i--) #define per2(i, n) for(ll i = n-1; i >= 0; i--) #define per3(i, a, b) for(ll i = b-1; i >= a; i--) #define per4(i, a, b, step) for(ll i = b-1; i >= a; i-= step) #define per(...) overload4(__VA_ARGS__, per4, per3, per2, per1)(__VA_ARGS__) //関数 #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() #define si(x) (ll)(x).size() templateinline bool chmax(S& a, T b){return a < b && ( a = b , true);} templateinline bool chmin(S& a, T b){return a > b && ( a = b , true);} inline void yes(){cout << "Yes\n";} inline void no(){cout << "No\n";} inline void yesno(bool y = true){if(y)yes();else no();} //定数 constexpr ll mod = 998244353; constexpr ll minf=-(1<<29); constexpr ll inf=(1<<29); constexpr ll MINF=-(1LL<<60); constexpr ll INF=(1LL<<60); const int dx[4] ={-1, 0, 1, 0}; const int dy[4] ={ 0, 1, 0,-1}; const int dx8[8] ={-1,-1,-1, 0, 1, 1, 1, 0}; const int dy8[8] ={-1, 0, 1, 1, 1, 0,-1,-1}; ll solve(ll n); int main() { int t = 1; // cin >>t; while(t--){ ll n; cin >> n; cout << solve(n) << endl; } } /* せっかくなので、PPC は全てコメント書きます N < 10^12 とかだったら簡単に解けるけど (等差数列の区間の総和は0(1) なのでそれにかけられる数字を計算(10^6くらいの区間)) N * sqrt(N) の計算は 同じ数字のところはまとめるとして、 m*m から (m+1)*(m+1)-1 までのsum を考えると (m*m + (m+1)*(m+1)-1) ((m+1)*(m+1)-m*m) / 2 * m = m^2(m+1)(2m+1) これの総和をとるので、 2m^4 + 3m^3 + m^2 の総和を考える これは簡単で、それぞれの項について考えると mint f(mint) の形になる あとは頑張って計算するしかなさそう 2^60 > 10^18 なので、60上根まで考えればいい */ #include using namespace atcoder; using mint = modint998244353; mint f(mint x) { return x * (x+1) * (2*x+1) * (3*x*x + 3*x - 1) / 15 + (x * (x + 1) / 2) * (x * (x + 1) / 2) * 3 + x * (x+1) * (2*x+1) / 6; } // min(x^n, INF) を返す (O(n)) ll sani(ll x, ll n) { ll res = 1; rep(i,0,n) { if(res > INF/x) { return INF; } res *= x; } return res; } ll sqrtll(ll x) { ll res = sqrtl(x); while(res*res < x) res++; while(res*res > x) res--; return res; } // 閉区間で与える mint calc(ll l, ll r) { ll ml = sqrtll(l); ll mr = sqrtll(r); if(ml == mr) { return mint(ml)*(r+l)*(r-l+1)/2; } mint ans = 0; ans += f(mr-1) - f(ml); ans += calc(l, (ml+1)*(ml+1)-1); ans += calc(mr*mr, r); return ans; } ll solve(ll n){ vector> mul; rep(j,3,60) { rep(i,2,1000001) { ll x = sani(i, j); if(x > n) break; mul.push_back({x, mint(i) / (i-1)}); } } sort(all(mul), [&](pair a, pair b) { return a.first < b.first; }); ll nw = 1; int now = 0; mint ans = 0; mint ml = 1; while(nw <= n) { if(now < mul.size()) { ll nx = mul[now].first-1; ans += calc(nw, nx) * ml; nw = nx+1; while(now < mul.size() && mul[now].first == nw) { ml *= mul[now].second; now++; } }else { ans += calc(nw, n) * ml; nw = n+1; } } return ans.val(); }