結果
問題 | No.1781 LCM |
ユーザー |
![]() |
提出日時 | 2024-09-19 00:47:15 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2,167 ms / 5,000 ms |
コード長 | 4,148 bytes |
コンパイル時間 | 3,253 ms |
コンパイル使用メモリ | 261,012 KB |
実行使用メモリ | 23,036 KB |
最終ジャッジ日時 | 2024-09-19 00:47:37 |
合計ジャッジ時間 | 17,049 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 31 |
ソースコード
#include<bits/stdc++.h>using namespace std;// [floor_sqrt(N)]// 0 <= N <= 9e18long long floor_sqrt(long long N) {long long ub = 3'000'000'001;long long lb = 0;while (ub - lb > 1) {long long t = (ub + lb) / 2;if (t * t <= N) lb = t;else ub = t;}return lb;}// Quotientsstruct Quotients {long long sqrtN;long long N;long long M;std::vector<long long> data;Quotients(long long _N): N(_N) {sqrtN = floor_sqrt(N);data = std::vector<long long>(sqrtN);for (int i=1; i<=sqrtN; i++) {data[i-1] = i;}for (int i=sqrtN-1; i>=0; i--){if (N / data[i] == data[i]) continue;data.emplace_back(N / data[i]);}M = data.size();}int size() {return M;}long long operator[](int i) {if (i < 0 || i >= M){throw std::out_of_range("Index out of range");}return data[i];}int ind(long long x) {if (x <= sqrtN) return x - 1;return M - N / x;}std::pair<long long, long long> interval(long long v) {return std::pair(N / (v+1) + 1, N / v + 1);}};// Lucy DP// returns (dp, prime_count)template <typename T, T (*g)(long long), T (*G)(long long)>std::pair<std::vector<T>, std::vector<long long>> lucy_dp(long long N) {Quotients Q(N);int m = Q.size();std::vector<T> dp(m);std::vector<long long> dp2(m);for (int i=0; i<m; i++){dp[i] = G(Q[i]) - g(1);dp2[i] = Q[i] - 1;}for (int x=2; x<=Q.sqrtN; x++){if (dp2[x-1] > dp2[x-2]) {long long border = (long long)x * x;for (int i=m-1; i>=0; i--){if (Q[i] < border) break;int tmpind = Q.ind(Q[i]/x);dp[i] -= g(x) * (dp[tmpind] - dp[x-2]);dp2[i] -= dp2[tmpind] - dp2[x-2];}}}return std::pair(dp, dp2);}// enumerate primes <= Nstd::vector<long long> enumerate_prime(long long N) {std::vector<bool> p(N+1);std::vector<long long> ret(0);for (long long i=2; i<=N; i++){if (p[i]) continue;ret.emplace_back(i);for (long long j=2*i; j<=N; j+=i){p[j] = true;}}return ret;}// black algorithm// recommended for N <= 1e12template<typename T, T(*f) (long long, long long, long long)>T black_algorithm(std::vector<T> GF,long long N) {if (N == 1) return 1;Quotients Q(N);std::vector<long long> prime_list = enumerate_prime(Q.sqrtN);int pm = prime_list.size();auto dfs = [&](auto self,long long num,T f_old,long long gpf,long long c,long long num_tamari) -> T {T ret = 0;if (gpf >= 0&& num * prime_list[gpf] <= N) {ret += f_old * f(prime_list[gpf], c+1, num_tamari * prime_list[gpf]);if (num * prime_list[gpf] * prime_list[gpf] <= N){ret += self(self,num * prime_list[gpf],f_old,gpf,c + 1,num_tamari * prime_list[gpf]);}}if (gpf >= 0){int lft = Q.ind(prime_list[gpf]);int rgt = Q.ind(N / num);if (lft < rgt){ret += f_old * f(prime_list[gpf], c, num_tamari) * (GF[rgt] - GF[lft]);}}else{int lft = 0;int rgt = Q.ind(N / num);if (lft < rgt){ret += GF[rgt] - GF[lft];}}for (long long i=gpf+1; i<pm; i++){if (num * prime_list[i] <= N&& num * prime_list[i] * prime_list[i] <= N) {if (gpf >= 0){ret += self(self,num * prime_list[i],f_old * f(prime_list[gpf], c, num_tamari),i,1,prime_list[i]);}else{ret += self(self,num * prime_list[i],f_old,i,1,prime_list[i]);}}else{break;}}return ret;};return dfs(dfs, 1, 1, -1, 0, 1) + T(1);}#include<atcoder/modint>typedef atcoder::modint998244353 mint;typedef long long ll;mint t[60];mint f(ll p, ll e, ll n) {return t[e+1];}mint g(ll p) {return 1;}mint G(ll p){return p;}int main(){ios_base::sync_with_stdio(false);cin.tie(NULL);ll n, m; cin >> n >> m;for (int i=1; i<60; i++){t[i] = mint(i).pow(n);}auto [a,b] = lucy_dp<mint,g,G>(m);vector<mint> x((int)a.size());mint tmp = mint(2).pow(n);for (int i=0; i<(int)a.size(); i++){x[i] = a[i] * tmp;}mint ans = black_algorithm<mint,f>(x,m);cout << ans.val() << '\n';}