結果
| 問題 |
No.1529 Constant Lcm
|
| コンテスト | |
| ユーザー |
risujiroh
|
| 提出日時 | 2021-06-04 20:59:44 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 10 ms / 3,000 ms |
| コード長 | 3,842 bytes |
| コンパイル時間 | 2,243 ms |
| コンパイル使用メモリ | 199,152 KB |
| 最終ジャッジ日時 | 2025-01-21 22:48:07 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 24 |
ソースコード
#include <bits/stdc++.h>
template <class T, class Int> T power(T a, Int n) {
__glibcxx_assert(n >= 0);
if (n == 0) return 1;
for (; ~n & 1; n >>= 1) a *= a;
T res = a;
while (n >>= 1) {
a *= a;
if (n & 1) res *= a;
}
return res;
}
template <class> class GetInverse;
template <uint32_t P> class Fp {
public:
static_assert([](int n) -> bool {
for (int i = 2; i * i <= n; ++i)
if (n % i == 0) return false;
return 3 <= n and n < 1 << 30;
}(P));
static constexpr int mod() { return P; }
Fp() : v(0) {}
template <class Int> Fp(const Int& a) : v(a % mod()) { v = (uint64_t(v + P) << 32) % P; }
int val() const {
int res = reduce(v) - P;
return res < 0 ? res + P : res;
}
Fp& operator++() { return *this += 1; }
Fp& operator--() { return *this -= 1; }
Fp& operator*=(Fp o) { return v = reduce(uint64_t(v) * o.v), *this; }
Fp& operator/=(Fp o) { return *this *= GetInverse<Fp>{}(o); }
Fp& operator+=(Fp o) { return v = int(v += o.v - 2 * P) < 0 ? v + 2 * P : v, *this; }
Fp& operator-=(Fp o) { return v = int(v -= o.v) < 0 ? v + 2 * P : v, *this; }
friend Fp operator++(Fp& a, int) { return std::exchange(a, ++Fp(a)); }
friend Fp operator--(Fp& a, int) { return std::exchange(a, --Fp(a)); }
friend Fp operator+(Fp a) { return a; }
friend Fp operator-(Fp a) { return Fp{} -= a; }
friend Fp operator*(Fp a, Fp b) { return a *= b; }
friend Fp operator/(Fp a, Fp b) { return a /= b; }
friend Fp operator+(Fp a, Fp b) { return a += b; }
friend Fp operator-(Fp a, Fp b) { return a -= b; }
friend bool operator==(Fp a, Fp b) { return a.v == b.v or a.v + P == b.v or a.v == b.v + P; }
friend bool operator!=(Fp a, Fp b) { return not(a == b); }
private:
static constexpr uint32_t R = []() -> uint32_t {
uint32_t res = -P;
for (int _ = 4; _--;) res *= P * res + 2;
return res;
}();
static uint32_t reduce(uint64_t x) { return (x + P * uint64_t(R * uint32_t(x))) >> 32; }
uint32_t v;
};
template <uint32_t P> class GetInverse<Fp<P>> {
public:
static void init(int n) {
inv.reserve(n + 1);
for (int i = std::size(inv); i <= n;) {
int q = P / i, j = std::min<int>(P / q, n);
for (; i <= j; ++i) inv.push_back(-q * inv[P - q * i]);
}
}
Fp<P> operator()(Fp<P> a) const {
__glibcxx_assert(a.val());
if ((-a).val() < int(std::size(inv))) return -inv[(-a).val()];
int y0 = 0, z0 = P, y1 = 1, z1 = a.val();
while (z1 >= std::max<int>(std::size(inv), 2)) std::swap(y0 -= z0 / z1 * y1, y1), std::swap(z0 %= z1, z1);
return z1 > 1 ? y1 * inv[z1] : y1;
}
private:
static inline std::vector<Fp<P>> inv{0, 1};
};
namespace linear_sieve {
std::vector<int> primes, lpf;
void init(int n) {
if (n < int(std::size(lpf))) return;
if (n < 2 * int(std::size(lpf))) n = 2 * std::size(lpf);
lpf.resize(n + 1, -1);
for (int d = 2; d <= n; ++d) {
if (lpf[d] == -1) lpf[d] = d, primes.push_back(d);
for (int p : primes) {
if (p * d > n or p > lpf[d]) break;
lpf[p * d] = p;
}
}
}
std::vector<int> factor(int n) {
__glibcxx_assert(n >= 1);
std::vector<int> res;
for (init(n); n > 1; n /= res.back()) res.push_back(lpf[n]);
return res;
}
} // namespace linear_sieve
int main() {
using namespace std;
cin.tie(nullptr)->sync_with_stdio(false);
int n;
cin >> n;
linear_sieve::init(n - 1);
using Mint = Fp<998244353>;
Mint ans = 1;
for (int p : linear_sieve::primes) {
int t = n, e = 0;
while (t > p and t % p == 0) {
t /= p;
++e;
}
int64_t cur = 1;
int f = 0;
while (cur * p < t) {
cur *= p;
++f;
}
ans *= power<Mint>(p, 2 * e + f);
}
cout << ans.val() << '\n';
}
risujiroh