結果
問題 | No.2318 Phys Bone Maker |
ユーザー | 7iz6 |
提出日時 | 2023-05-26 22:55:36 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 9,711 bytes |
コンパイル時間 | 2,024 ms |
コンパイル使用メモリ | 162,752 KB |
実行使用メモリ | 14,956 KB |
最終ジャッジ日時 | 2024-06-07 08:29:52 |
合計ジャッジ時間 | 6,354 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 5 ms
14,136 KB |
testcase_01 | AC | 5 ms
7,168 KB |
testcase_02 | TLE | - |
testcase_03 | -- | - |
testcase_04 | -- | - |
testcase_05 | -- | - |
testcase_06 | -- | - |
testcase_07 | -- | - |
testcase_08 | -- | - |
testcase_09 | -- | - |
testcase_10 | -- | - |
testcase_11 | -- | - |
testcase_12 | -- | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
testcase_19 | -- | - |
testcase_20 | -- | - |
testcase_21 | -- | - |
testcase_22 | -- | - |
testcase_23 | -- | - |
testcase_24 | -- | - |
testcase_25 | -- | - |
testcase_26 | -- | - |
testcase_27 | -- | - |
testcase_28 | -- | - |
testcase_29 | -- | - |
testcase_30 | -- | - |
testcase_31 | -- | - |
testcase_32 | -- | - |
testcase_33 | -- | - |
testcase_34 | -- | - |
testcase_35 | -- | - |
testcase_36 | -- | - |
testcase_37 | -- | - |
testcase_38 | -- | - |
testcase_39 | -- | - |
testcase_40 | -- | - |
testcase_41 | -- | - |
testcase_42 | -- | - |
testcase_43 | -- | - |
testcase_44 | -- | - |
testcase_45 | -- | - |
testcase_46 | -- | - |
testcase_47 | -- | - |
ソースコード
#include <iostream> #include <vector> #include <queue> #include <map> #include <stack> #include <string> #include <set> #include <tuple> #include <bitset> #include <array> #include <unordered_map> #include <unordered_set> #include <algorithm> #include <numeric> #include <utility> #include <cmath> #include <cstdio> #include <cstring> #include <iterator> #include <limits> #include <iomanip> #include <cassert> #include <sstream> #include <random> #include <memory> // #include <boost/container/flat_set.hpp> // insert: O(log N), erase: O(1) // using namespace boost::container // #include <atcoder/all> // using namespace atcoder; using namespace std; #define rep(i, n) for (int i = 0; i < (n); ++i) #define ll long long #define pii std::pair<int, int> #define pll std::pair<ll, ll> #define vi std::vector<int> #define vii std::vector<std::pair<int, int>> #define vll std::vector<std::pair<ll, ll>> #define vvi std::vector<std::vector<int>> #define vvl std::vector<std::vector<ll>> #define ALL(v) (v).begin(), (v).end() #define OUT(v) for(int i = 0, n = (v).size(); i < n; i++) cout << v[i] << " \n"[i+1==n] // const int MOD = 1e9 + 7; const int MOD = 998244353; const ll LINF = 1001002003004005006ll; const int INF = 1001001001; const double eps = 1e-6; constexpr double PI = std::acos(-1); const int di[4] = {0, 1, 0, -1}; const int dj[4] = {1, 0, -1, 0}; const int di8[8] = {0, 1, 1, 1, 0, -1, -1, -1}; const int dj8[8] = {1, 1, 0, -1, -1, -1, 0, 1}; template<typename T, typename U> bool operator==(const pair<T, U>& lhs, const pair<T, U>& rhs) { return (lhs.first == rhs.first && lhs.second == rhs.second); } bool is_out(int i, int j, int n) { return (i < 0 || j < 0 || i >= n || j >= n); } bool is_out(int i, int j, int h, int w) { return (i < 0 || j < 0 || i >= h || j >= w); } template <typename T> bool PN(T x){if(x <= 1)return false;if(x == 2)return true;for(ll i = 2; i * i <= x; i++)if(x % i == 0)return false; return true;} ll Comb(int n, int i){ll ans=1;if(i>n||i<0)return 0;if(i==0||i==n)return 1;else{for(int j=1;j<=i;++j){ans*=(n+1-j);ans/=j;ans%=MOD;}}return ans;} template <typename T>T gcd(T a, T b){if (a < b)std::swap(a,b);return (b==0)?a:gcd(b,a%b);} template <typename T> T lcm(T a, T b){if(b>a)std::swap(a,b);T g=gcd(a,b);return a/g*b;} template <typename T> void chmax(T& a, T b) {a=b>a?b:a;} template <typename T> void chmin(T& a, T b) {a=b<a?b:a;} // 約数列挙 template<typename T> vector<T> divisor(T n) { vector<T> res; for (long long i = 1; i * i <= n; i++) { if (n % i == 0) { res.push_back(i); if (i != n / i) { res.push_back(n / i); } } } sort(res.begin(), res.end()); return res; } template <class T> T modpow(T a, T b, T mod) { // a^b mod m を求める long long p=1,q=a; for(int i = 0; i < 30; i++) { if((b & (1LL << i)) != 0) p*=q, p%=mod; q*=q; q%=mod; } return p; } template <class T> T Div(T a, T b, T m) { return (a * modpow(b, m - 2, m)) % m; } // 区間更新遅延評価セグ木(葉の値を別の値に更新) // 区間の最大値を返す(RMQ)。 namespace seg_update { using S = ll; using F = ll; const ll ID = 1e18 + 1; const int N_SEG = 1e5 + 5; S op(S l, S r) { return max(l, r); } S e() { return 0; } S mapping(F l, S r) { return l; } F composition(F f, F g) { return (f == ID) ? g : f; } F id() { return ID; } // atcoder::lazy_segtree<S, op, e, F, mapping, composition, id> seg(N_SEG); } // 区間加算遅延評価セグ木(葉の値を定数倍+定数加算) ai <- ai * a + b; // 区間の和を返す。 namespace seg_add{ struct S { ll a; int size; }; struct F { ll a, b; }; S op(S l, S r) { return S{l.a + r.a, l.size + r.size}; } S e() { return S{0, 0}; } S mapping(F l, S r) { return S{r.a * l.a + r.size * l.b, r.size}; } F composition(F f, F g) { return F{g.a * f.a, g.b * f.a + f.b}; } F id() { return {1, 0}; } } /// @brief 重み付き Union-Find 木 /// @tparam Type 重みの表現に使う型 /// @note 1.1 シンプルな実装 /// @see https://zenn.dev/reputeless/books/standard-cpp-for-competitive-programming/viewer/weighted-union-find template <class Type> class WeightedUnionFind { public: WeightedUnionFind() = default; /// @brief 重み付き Union-Find 木を構築します。 /// @param n 要素数 explicit WeightedUnionFind(size_t n) : m_parents(n) , m_sizes(n, 1) , m_diffWeights(n) { std::iota(m_parents.begin(), m_parents.end(), 0); } /// @brief 頂点 i の root のインデックスを返します。 /// @param i 調べる頂点のインデックス /// @return 頂点 i の root のインデックス int find(int i) { if (m_parents[i] == i) { return i; } const int root = find(m_parents[i]); m_diffWeights[i] += m_diffWeights[m_parents[i]]; // 経路圧縮 return (m_parents[i] = root); } /// @brief a のグループと b のグループを統合します。 /// @param a 一方のインデックス /// @param b 他方のインデックス /// @param w (b の重み) - (a の重み) void merge(int a, int b, Type w) { w += weight(a); w -= weight(b); a = find(a); b = find(b); if (a != b) { // union by size (小さいほうが子になる) if (m_sizes[a] < m_sizes[b]) { std::swap(a, b); w = -w; } m_sizes[a] += m_sizes[b]; m_parents[b] = a; m_diffWeights[b] = w; } } /// @brief (b の重み) - (a の重み) を返します。 /// @param a 一方のインデックス /// @param b 他方のインデックス /// @remark a と b が同じグループに属さない場合の結果は不定です。 /// @return (b の重み) - (a の重み) Type diff(int a, int b) { return (weight(b) - weight(a)); } /// @brief a と b が同じグループに属すかを返します。 /// @param a 一方のインデックス /// @param b 他方のインデックス /// @return a と b が同じグループに属す場合 true, それ以外の場合は false bool connected(int a, int b) { return (find(a) == find(b)); } /// @brief i が属するグループの要素数を返します。 /// @param i インデックス /// @return i が属するグループの要素数 int size(int i) { return m_sizes[find(i)]; } private: // m_parents[i] は i の 親, // root の場合は自身が親 std::vector<int> m_parents; // グループの要素数 (root 用) // i が root のときのみ, m_sizes[i] はそのグループに属する要素数を表す std::vector<int> m_sizes; // 重み std::vector<Type> m_diffWeights; Type weight(int i) { find(i); // 経路圧縮 return m_diffWeights[i]; } }; template<typename T> size_t LIS(const std::vector<T>& v) { size_t sz = v.size(); std::vector<T> ret; for(const T& val: v) { auto it = std::lower_bound(ret.begin(), ret.end(), val); if(it == ret.end()) { ret.push_back(val); } else { *it = val; } } return ret.size(); } struct UndirectedGraph { std::vector<std::vector<pair<int, long long>>> G; std::vector<int> u, v; std::vector<long long> w; int n; int m; UndirectedGraph(int _n, int _m) { n = _n; m = _m; u.resize(n); v.resize(n); w.resize(n, 1); G.resize(n + 10); } void read_uv() { for(int i = 0; i < m; i++) { cin >> u[i] >> v[i]; u[i]--; v[i]--; G[u[i]].push_back({v[i], 1}); G[v[i]].push_back({u[i], 1}); } } void read_uvw() { for(int i = 0; i < m; i++) { cin >> u[i] >> v[i] >> w[i]; u[i]--; v[i]--; G[u[i]].push_back({v[i], w[i]}); G[v[i]].push_back({u[i], w[i]}); } } // return distance and pre points std::pair<std::vector<long long>, std::vector<int>> dijkstra(int s) { typedef std::pair<long long, pair<int,int> > Edge; std::vector<long long> dist(n, LINF); std::vector<int> pre(n, -1); dist[s] = 0; pre[s] = s; std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge> > pq; pq.push(Edge{0, {s, -1}}); while(!pq.empty()) { Edge e = pq.top(); pq.pop(); int from = e.second.first; long long cost = e.first; if(dist[from] < cost) continue; for(auto[nx, weight]: G[from]) { if(dist[nx] > dist[from] + weight) { dist[nx] = dist[from] + weight; pq.push(Edge{dist[nx], {nx, from}}); pre[nx] = from; } } } return {dist, pre}; } }; void solve(){ long long n; cin >> n; long long n2 = n; vector<long long> div = divisor(n); vector<int> cnt(1000001, 0); for(long long i = 2; i * i <= n; i++) { for(long long j = i; j * j <= n; j += i) { cnt[j]++; } } vector<int> primes; for(int i = 2; i <= 1000000; i++) { if(cnt[i] == 1) primes.push_back(i); } map<long long, long long> dp; dp[1] = 1; vector<pair<long long, int>> v; for(int p: primes) { int cnt = 0; while(n2%p==0) { cnt++; n2/=p; } if(cnt>0) v.push_back({p, cnt}); } if(n2 != 0) v.push_back({n2, 1}); vector<long long> muls; muls.push_back(1); for(auto p: v) { int msize = muls.size(); long long val = 1; for(int i = 0; i < p.second; i++) { val *= (ll)p.first; for(int j = 0; j < msize; j++) muls.push_back((ll)muls[j] * val); } } sort(muls.begin(), muls.end()); muls.erase(unique(muls.begin(), muls.end()), muls.end()); for(auto val: muls) cerr << val << " "; cerr << endl; cerr << muls.size() << " " << div.size() << endl; for(long long d: div) { for(long long mul: muls) { if(long long l = lcm(d, mul); l > d) { dp[l] += dp[d]; dp[l] %= MOD; } } } cout << dp[n] << endl; } int main(void){ solve(); return 0; }