#include #include #include #include #include class PrimeCounting{ using i64 = long long; i64 n; i64 sqrtn; std::vector prefix_sum_devil; std::vector prefix_sum_fairy; PrimeCounting(i64 maxval){ n = maxval; sqrtn = 0; while(sqrtn * sqrtn <= n) sqrtn++; sqrtn--; prefix_sum_fairy.assign(sqrtn+1, 0); prefix_sum_fairy[0] = 0; for(i64 i=1; i<=sqrtn; i++) prefix_sum_fairy[i] = i-1; prefix_sum_devil.assign(sqrtn+1, 0); for(i64 i=1; i<=sqrtn; i++) prefix_sum_devil[i] = n/i-1; for(i64 p=2; p<=sqrtn; p++){ i64 prime_count_p = prefix_sum_fairy[p]; i64 prime_count_p_minus1 = prefix_sum_fairy[p-1]; if(prime_count_p == prime_count_p_minus1) continue; for(i64 devil_id = 1; devil_id <= sqrtn; devil_id++){ if(devil_id * p <= sqrtn){ prefix_sum_devil[devil_id] -= prefix_sum_devil[devil_id * p] - prime_count_p_minus1; } else{ i64 tg_fairy = n / (devil_id * p); if(tg_fairy < p) break; prefix_sum_devil[devil_id] -= prefix_sum_fairy[tg_fairy] - prime_count_p_minus1; } } for(i64 fairy_id = sqrtn/p; fairy_id >= p; fairy_id--){ i64 dc = prefix_sum_fairy[fairy_id] - prime_count_p_minus1; i64 max_tg = std::min(fairy_id * p + p - 1, sqrtn); for(i64 tg_fairy = fairy_id * p; tg_fairy <= max_tg; tg_fairy++) prefix_sum_fairy[tg_fairy] -= dc; } } } public: static long long solve(long long n){ if(n <= 1) return 0; auto res = PrimeCounting(n); return res.prefix_sum_devil[1]; } static std::pair, std::vector> solve_sqrt_decomposition(long long n){ if(n <= 1) return std::make_pair(std::vector{0}, std::vector{0}); auto res = PrimeCounting(n); return std::make_pair(std::move(res.prefix_sum_fairy), std::move(res.prefix_sum_devil)); } }; const unsigned int MOD = 998244353; long long N, M; std::vector> precalc; class CompletelyMultiplicativePrefixSum{ public: using E = atcoder::static_modint; using vecE = std::vector; using i64 = long long; static std::pair primesafe_sum(i64 n, i64 floor_sqrt_n){ vecE fairies(floor_sqrt_n+1, 0); for(i64 i=0; i<=floor_sqrt_n; i++) fairies[i] = precalc[1] * i; vecE devils(floor_sqrt_n+1, 0); for(i64 i=1; i<=floor_sqrt_n; i++) devils[i] = precalc[1] * (n/i); return std::make_pair(std::move(fairies), std::move(devils)); } static E primesafe_linearity_over_primepower(E fx, i64 pp){ return fx; } static E optional_multiplicative_function(i64 p, i64 e){ // return E(e+1).pow(N); return precalc[e]; } private: i64 n; i64 sqrtn; std::vector isprime_table; vecE primesafe_fairy; vecE fairies; vecE devils; CompletelyMultiplicativePrefixSum(i64 maxval){ n = maxval; sqrtn = 0; while(sqrtn * sqrtn <= n) sqrtn++; sqrtn--; //std::cout << "sqrtn = " << sqrtn << std::endl; isprime_table.assign(sqrtn+1, 1); isprime_table[0] = isprime_table[1] = 0; { auto res_primesafe = primesafe_sum(n, sqrtn); fairies = std::move(res_primesafe.first); devils = std::move(res_primesafe.second); primesafe_fairy = fairies; for(int i=sqrtn; i>=1; i--) primesafe_fairy[i] -= primesafe_fairy[i-1]; for(i64 p=2; p<=sqrtn; p++) fairies[p] -= fairies[1]; for(i64 p=1; p<=sqrtn; p++) devils[p] -= fairies[1]; fairies[1] = 0; primesafe_fairy[1] = 0; } //std::cout << "CompletelyMultiplicativePrefixSum layer 0" << std::endl; //std::cout << "fairy : [ "; for(auto a : fairies) std::cout << a.val() << " "; std::cout << "]" << std::endl; //std::cout << "devil : [ "; for(auto a : devils) std::cout << a.val() << " "; std::cout << "]" << std::endl; for(i64 p=2; p<=sqrtn; p++){ if(isprime_table[p] == 0) continue; for(i64 i=p*p; i<=sqrtn; i+=p) isprime_table[i] = 0; E prime_count_p_minus1 = fairies[p-1]; for(i64 devil_id = 1; devil_id <= sqrtn; devil_id++){ if(devil_id * p <= sqrtn){ devils[devil_id] -= primesafe_linearity_over_primepower(devils[devil_id * p] - prime_count_p_minus1, p); } else{ i64 tg_fairy = n / (devil_id * p); if(tg_fairy < p) break; devils[devil_id] -= primesafe_linearity_over_primepower(fairies[tg_fairy] - prime_count_p_minus1, p); } } for(i64 fairy_id = sqrtn/p; fairy_id >= p; fairy_id--){ E dc = primesafe_linearity_over_primepower(fairies[fairy_id] - prime_count_p_minus1, p); i64 max_tg = std::min(fairy_id * p + p - 1, sqrtn); for(i64 tg_fairy = fairy_id * p; tg_fairy <= max_tg; tg_fairy++) fairies[tg_fairy] -= dc; } } //std::cout << "CompletelyMultiplicativePrefixSum layer 1" << std::endl; //std::cout << "fairy : [ "; for(auto a : fairies) std::cout << a.val() << " "; std::cout << "]" << std::endl; //std::cout << "devil : [ "; for(auto a : devils) std::cout << a.val() << " "; std::cout << "]" << std::endl; for(i64 p=sqrtn; p>=2; p--){ if(isprime_table[p] == 0) continue; E prime_count_p_minus1 = fairies[p-1]; for(i64 fairy_id = p; fairy_id <= sqrtn/p; fairy_id++){ E dc = (fairies[fairy_id] - prime_count_p_minus1) * primesafe_fairy[p]; i64 max_tg = std::min(fairy_id * p + p - 1, sqrtn); for(i64 tg_fairy = fairy_id * p; tg_fairy <= max_tg; tg_fairy++) fairies[tg_fairy] += dc; } for(i64 devil_id = std::min(sqrtn, n / (p*p)); devil_id >= 1; devil_id--){ if(devil_id * p <= sqrtn){ devils[devil_id] += (devils[devil_id * p] - prime_count_p_minus1) * primesafe_fairy[p]; } else{ i64 tg_fairy = n / (devil_id * p); devils[devil_id] += (fairies[tg_fairy] - prime_count_p_minus1) * primesafe_fairy[p]; } } } for(i64 p=1; p<=sqrtn; p++) fairies[p] += 1; for(i64 p=1; p<=sqrtn; p++) devils[p] += 1; //std::cout << "CompletelyMultiplicativePrefixSum layer 2" << std::endl; //std::cout << "fairy : [ "; for(auto a : fairies) std::cout << a.val() << " "; std::cout << "]" << std::endl; //std::cout << "devil : [ "; for(auto a : devils) std::cout << a.val() << " "; std::cout << "]" << std::endl; } E interpolation_sum(){ /* std::vector primes; for(int p=2; p<=sqrtn; p++) if(isprime_table[p]) primes.push_back(p); std::functionrec=[&](i64 pn,int beg,E coef){ if(coef==0)return E(0); E ret=coef*(pn>sqrtn?devils[n/pn]:fairies[pn]); for(int i=beg;i<(int)primes.size();i++){ i64 p=primes[i],nn=pn/p/p; if(nn==0)break; for(int e=2;nn;nn/=p,e++){ ret+=rec(nn,i+1,coef*(optional_multiplicative_function(p,e)-optional_multiplicative_function(p,1)*optional_multiplicative_function(p,e-1))); } } return ret; }; return rec(n,0,1); */ vecE e_fairies(sqrtn+1, 0); vecE e_devils(sqrtn+1, 0); e_devils[1] = 1; std::vector power_p; power_p.resize(100); std::vector coeff_diff; coeff_diff.resize(100); for(i64 p=2; p<=sqrtn; p++) if(isprime_table[p]){ power_p[1] = p; for(int e = 2; p <= n / power_p[e-1]; e++){ power_p[e] = power_p[e-1] * p; coeff_diff[e] = optional_multiplicative_function(p, e) - optional_multiplicative_function(p, e-1) * optional_multiplicative_function(p, 1); power_p[e+1] = n+1; } i64 max_fairy_id = sqrtn / power_p[2]; for(i64 fairy_id = power_p[2]; fairy_id <= sqrtn; fairy_id++){ i64 tg_fairy = fairy_id / power_p[2]; for(int e = 2; tg_fairy >= 1; e++, tg_fairy /= p){ e_fairies[tg_fairy] += e_fairies[fairy_id] * coeff_diff[e]; } } for(i64 devil_id = std::min(sqrtn, n / power_p[2]); devil_id >= 1; devil_id--){ i64 devil_size = n / (devil_id * power_p[2]); for(int e = 2; devil_size >= 1; e++, devil_size /= p){ //std::cout << "e = " << e << std::endl; if(devil_size > sqrtn) e_devils[n / devil_size] += e_devils[devil_id] * coeff_diff[e]; else e_fairies[devil_size] += e_devils[devil_id] * coeff_diff[e]; } //std::cout << "devil_id = " << devil_id << std::endl; } //std::cout << "p = " << p << std::endl; //std::cout << "fairy : [ "; for(auto a : e_fairies) std::cout << a.val() << " "; std::cout << "]" << std::endl; //std::cout << "devil : [ "; for(auto a : e_devils) std::cout << a.val() << " "; std::cout << "]" << std::endl; } E res = 0; for(i64 fairy_id = 1; fairy_id <= sqrtn; fairy_id++) res += fairies[fairy_id] * e_fairies[fairy_id]; for(i64 devil_id = 1; devil_id <= sqrtn; devil_id++) res += devils[devil_id] * e_devils[devil_id]; return res; } public: static std::pair solve(long long n){ auto res = CompletelyMultiplicativePrefixSum(n); return std::make_pair(std::move(res.fairies), std::move(res.devils)); } static E solve_general_multiplicative_sum(long long n){ auto res = CompletelyMultiplicativePrefixSum(n); return res.interpolation_sum(); } }; #include struct ios_do_not_sync{ ios_do_not_sync(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); } } ios_do_not_sync_instance; int main() { std::cin >> N >> M; precalc.assign(100, 1); for(int e=0; e<=100; e++) precalc[e] = atcoder::static_modint(e+1).pow(N); auto ans = CompletelyMultiplicativePrefixSum::solve_general_multiplicative_sum(M); std::cout << ans.val() << std::endl; return 0; }