結果
問題 | No.1781 LCM |
ユーザー | 👑 Nachia |
提出日時 | 2024-08-28 22:44:55 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 6,886 bytes |
コンパイル時間 | 1,382 ms |
コンパイル使用メモリ | 104,348 KB |
実行使用メモリ | 17,948 KB |
最終ジャッジ日時 | 2024-08-28 22:45:09 |
合計ジャッジ時間 | 12,166 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | WA | - |
testcase_01 | WA | - |
testcase_02 | WA | - |
testcase_03 | WA | - |
testcase_04 | WA | - |
testcase_05 | WA | - |
testcase_06 | WA | - |
testcase_07 | AC | 2 ms
6,940 KB |
testcase_08 | WA | - |
testcase_09 | WA | - |
testcase_10 | WA | - |
testcase_11 | WA | - |
testcase_12 | WA | - |
testcase_13 | WA | - |
testcase_14 | AC | 2 ms
6,940 KB |
testcase_15 | WA | - |
testcase_16 | WA | - |
testcase_17 | WA | - |
testcase_18 | WA | - |
testcase_19 | WA | - |
testcase_20 | RE | - |
testcase_21 | WA | - |
testcase_22 | AC | 2,045 ms
17,948 KB |
testcase_23 | WA | - |
testcase_24 | RE | - |
testcase_25 | WA | - |
testcase_26 | AC | 2,126 ms
17,848 KB |
testcase_27 | WA | - |
testcase_28 | WA | - |
testcase_29 | WA | - |
testcase_30 | RE | - |
testcase_31 | WA | - |
testcase_32 | AC | 2 ms
6,940 KB |
ソースコード
#include <iostream> #include <string> #include <vector> #include <algorithm> #include <utility> namespace nachia{ std::pair<std::vector<long long>, std::vector<long long>> CountingPrimesTable(long long maxval) { using i64 = long long; i64 n = maxval; if(n <= 1) return { {0,0}, {0,0} }; i64 sqrtn = 0; while(sqrtn * sqrtn <= n) sqrtn++; sqrtn--; std::vector<i64> prefix_sum_fairy(sqrtn+1, 0); for(i64 i=1; i<=sqrtn; i++) prefix_sum_fairy[i] = i-1; std::vector<i64> prefix_sum_devil(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; } } return std::make_pair(std::move(prefix_sum_fairy), std::move(prefix_sum_devil)); } long long CountingPrimes(long long maxval){ return CountingPrimesTable(maxval).second[1]; } } // namespace nachia namespace nachia { template<class Elem, class F1, class F2> std::pair<std::vector<Elem>, std::vector<Elem>> MultiplicativePrefixSum(long long N, F1 f1, F2 f2){ using i64 = long long; i64 Nr2 = 0; while((Nr2+1) * (Nr2+1) <= N) Nr2++; i64 Nr3 = 0; while((Nr3+1) * (Nr3+1) * (Nr3+1) <= N) Nr3++; i64 Nr6 = 0; while((Nr6+1) * (Nr6+1) <= Nr3) Nr6++; i64 N2r3 = std::max(Nr2, N / (N / Nr6 / Nr2 + 1)); i64 Dsz = N / (Nr2+1); i64 Asz = (Nr2+1) + Dsz; std::vector<Elem> A(Asz + 1, Elem(0)); auto Aat = [Asz,Nr2,N](i64 x) -> i64 { return x <= Nr2 ? x : (Asz-N/x); }; std::vector<int> sieve(Nr2+1, 1); sieve[0] = sieve[1] = 0; std::vector<i64> primes; for(i64 p=2; p<=Nr2; p++) if(sieve[p]){ primes.push_back(p); for(i64 q=p*p; q<=Nr2; q+=p) sieve[q] = 0; } i64 Nr2Pi = i64(primes.size()); i64 Nr3Pi = 0; while(Nr3Pi < Nr2Pi && primes[Nr3Pi] <= Nr3) Nr3Pi++; // 1 A[1] += Elem(1); // p for(i64 p : primes) if(Nr3 < p) A[p] = f1(p, 1, p); for(i64 i=1; i<=Dsz; i++) A[Asz-i] = f2(N/i); for(i64 i=1; i<Dsz; i++) A[Asz-i] -= A[Asz-(i+1)]; A[Asz-Dsz] -= f2(Nr2); // pq, p^2 for(i64 px=Nr3Pi; px<Nr2Pi; px++){ i64 p = primes[px]; A[Aat(p*p)] += f1(p, 2, p*p); // p^2 Elem fp = f1(p, 1, p); Elem ppre = f2(p); // pq (p<q) for(i64 i=N/(p*(p+1)); i>=1; i--){ Elem pnx = f2(N/(i*p)); A[Asz-i] += (pnx - ppre) * fp; ppre = pnx; } } for(i64 i=1; i+1<Asz; i++) A[i+1] += A[i]; auto getfpeBuf = [&](i64 p) -> std::pair<std::vector<i64>, std::vector<Elem>> { std::vector<Elem> fpebuf; std::vector<i64> pe; for(i64 pp=p, e=1; pp<=N; pp*=p, e++){ fpebuf.push_back(f1(p, e, pp)); pe.push_back(pp); } pe.push_back(N+1); return std::make_pair(std::move(pe), std::move(fpebuf)); }; std::vector<std::pair<std::vector<i64>, std::vector<Elem>>> fpebufall(Nr2Pi); for(i64 px=0; px<Nr2Pi; px++) fpebufall[px] = getfpeBuf(primes[px]); i64 px = Nr3Pi - 1; // setup fenwick tree i64 fwtSz = Aat(N2r3) + 1; auto fwAdd = [&](i64 i, Elem v) -> void { while(i < fwtSz){ A[i] += v; i += i & -i; } }; auto fwSum = [&](i64 r) -> Elem { Elem x = Elem(0); while(r > 0){ x += A[r]; r -= r & -r; } return x; }; for(i64 i=fwtSz-2; i>=1; i--) A[i+1] -= A[i]; for(i64 i=1; i<fwtSz; i++) if(i+(i&-i) < fwtSz) A[i+(i&-i)] += A[i]; auto getAsum = [&](i64 v) -> Elem { return v < fwtSz ? fwSum(v) : A[v]; }; for( ; px>=0 && primes[px]>Nr6; px--){ auto& [xpe, xfpe] = fpebufall[px]; // N2r3 <= n for(i64 x=1; Asz-x>=fwtSz; x++){ i64 n = N / x; for(i64 e=0; xpe[e]<=n; e++){ A[Asz-x] += xfpe[e] * getAsum(Aat(n/xpe[e])); } } // search v <= N2r3 && primes[px] == lpf(v) std::vector<std::pair<i64, Elem>> bfs; for(i64 e=0; xpe[e] <= N2r3; e++){ fwAdd(Aat(xpe[e]), xfpe[e]); bfs.push_back({ xpe[e], xfpe[e] }); } for(i64 pxv=px+1; pxv<Nr2Pi; pxv++){ auto& [vpe, vfpe] = fpebufall[pxv]; i64 p = vpe[0]; i64 bfsz = bfs.size(); for(i64 i=0; i<bfsz; i++){ auto [v, fv] = bfs[i]; for(i64 e=0; e<i64(vpe.size()); e++) if(v * vpe[e] <= N2r3){ i64 nx = v * vpe[e]; Elem nxval = fv * vfpe[e]; fwAdd(Aat(nx), nxval); if(nx*p <= N2r3) bfs.push_back({ nx, nxval }); } } } } for(i64 i=fwtSz-1; i>=1; i--) if(i+(i&-i) < fwtSz) A[i+(i&-i)] -= A[i]; for(i64 i=1; i<fwtSz-1; i++) A[i+1] += A[i]; for( ; px>=0; px--){ auto [pe, fpebuf] = std::move(fpebufall[px]); for(i64 i=1; i<=Dsz; i++){ for(i64 t=0; i*pe[t]<=N; t++){ A[Asz-i] += A[Aat(N/(i*pe[t]))] * fpebuf[t]; } } for(i64 i=Nr2; i>=pe[0]; i--){ for(i64 t=0; pe[t]<=i; t++){ A[i] += A[i/pe[t]] * fpebuf[t]; } } } return std::make_pair( std::vector<Elem>(A.begin(), A.begin() + Nr2), std::vector<Elem>(A.rbegin(), A.rbegin() + (Dsz + 1)) ); } } // namespace nachia #include <atcoder/modint> using Modint = atcoder::static_modint<998244353>; using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); using i64 = long long; i64 N; cin >> N; i64 M; cin >> M; vector<Modint> X(100); for(i64 i=1; i<100; i++) X[i] = Modint(i+1).pow(N); auto [pcf, pcd] = nachia::CountingPrimesTable(M); i64 s = i64(pcf.size() - 1); auto ans = nachia::MultiplicativePrefixSum<Modint>( N, [&](i64 p, i64 e, i64 pe){ return X[e]; }, [&](i64 x){ return Modint((x <= s ? pcf[x] : pcd[N/x]) * X[1]); }); cout << ans.second[1].val() << '\n'; return 0; }