結果

問題 No.2902 ZERO!!
ユーザー nana
提出日時 2025-01-10 09:14:40
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 222 ms / 2,000 ms
コード長 11,759 bytes
コンパイル時間 10,694 ms
コンパイル使用メモリ 363,548 KB
実行使用メモリ 23,220 KB
最終ジャッジ日時 2025-01-10 09:14:57
合計ジャッジ時間 15,419 ms
ジャッジサーバーID
(参考情報)
judge1 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 41
権限があれば一括ダウンロードができます

ソースコード

diff #

#ifndef ONLINE_JUDGE
#define _GLIBCXX_DEBUG
#endif
#include "atcoder/all"
#include <string>
#include <bits/stdc++.h>
#include <climits>
/*
Boostが使用したかったら WSLの方で開いて
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
#include <boost/functional/hash.hpp>
// 任意長整数型
using Bint = boost::multiprecision::cpp_int;
// 仮数部が10進数で1024桁の浮動小数点数型(TLEしたら小さくする)
using BReal =
    boost::multiprecision::number<boost::multiprecision::cpp_dec_float<1024>>;
using Rat = boost::rational<Bint>;
*/
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
// 型エイリアスの設定
template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using namespace atcoder;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<typename T> inline bool chmin(T &a, T b) { return ((a>b) ? (a = b, true) : (false));}
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define drep(i,n) for(int i=n-1;i>=0;i--)
#define REP(i,s,n) for(int i=s;i<(int)n;i++)
#define DREP(i,s,n) for(int i=n-1;i>=s;i--)
const long long inf = 1LL<<60;
const int infi = 1e9+1;
typedef long long ll;
typedef long double ld;
typedef __int128_t l3;
//cmpArg := 偏角ソート, atan2l(y, x); atan2l(y, x) = [-pi, pi]
#define cmpArg [](const auto &p1, const auto &p2) { return atan2l(p1.second, p1.first) < atan2l(p2.second, p2.first); }
typedef pair<int,int> pi;
typedef pair<ll,ll> pl;
#define vl vector<ll>
#define vvl vector<vector<ll>>
#define vi vector<int>
#define vvi vector<vector<int>>
#define vm vector<mint>
#define vvm vector<vector<mint>>
#define vvc vector<vector<char>>
#define vc vector<char>
#define vvpi vector<vector<pi>>
#define vpi vector<pi>
#define vpl vector<pl>
#define vvpl vector<vector<pl>>
#define pb push_back
#define eb emplace_back
#define YES cout<<"Yes"<<endl;
#define NO cout<<"No"<<endl;
#define YN { cout << "Yes" << endl; } else { cout << "No" << endl; }
#define all(x) x.begin(), x.end()
#define rall(i) std::rbegin(i), std::rend(i)
#define len(x) ((ll)(x).size())
#define fi first
#define se second
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
int pc(ll x) { return __builtin_popcount(x); } //ビット列にどれだけ1がたっているかを求める pop count
void cincout(){  ios::sync_with_stdio(false);   std::cin.tie(nullptr);  cout<< fixed << setprecision(15);  }
bool out_grid(ll i, ll j, ll h, ll w) { return (!(0<=i && i<h && 0<=j && j<w)); }
inline void read(int &a) { std::cin >> a; }
inline void read(unsigned &a) { std::cin >> a; }
inline void read(long &a) { std::cin >> a; }
inline void read(long long &a) { std::cin >> a; }
inline void read(unsigned long long &a) { std::cin >> a; }
inline void read(char &a) { std::cin >> a; }
inline void read(float &a) { std::cin >> a; }
inline void read(double &a) { std::cin >> a; }
inline void read(long double &a) { std::cin >> a; }
inline void read(std::vector<bool> &vec) {
    for (int32_t i = 0; i < vec.size(); i++) {
        int a;
        read(a);
        vec[i] = a;
    }
}
inline void read(std::string &a) { std::cin >> a; }
template <class T>
inline void read(std::vector<T> &vec);
template <class T, size_t size>
inline void read(std::array<T, size> &vec);
template <class T, class L>
inline void read(std::pair<T, L> &p);
template <class T, size_t size>
inline void read(T (&vec)[size]);
template <class T>
inline void read(std::vector<T> &vec) {
    for (auto &i : vec) read(i);
}
template <class T>
inline void read(std::deque<T> &vec) {
    for (auto &i : vec) read(i);
}
template <class T, size_t size>
inline void read(std::array<T, size> &vec) {
    for (auto &i : vec) read(i);
}
template <class T, class L>
inline void read(std::pair<T, L> &p) {
    read(p.first);
    read(p.second);
}
template <class T, size_t size>
inline void read(T (&vec)[size]) {
    for (auto &i : vec) read(i);
}
template <class T>
inline void read(T &a) {
    std::cin >> a;
}
inline void in() {}
template <class Head, class... Tail>
inline void in(Head &head, Tail &...tail) {
    read(head);
    in(tail...);
}
inline void print() { std::cout << ' '; }
inline void print(const bool &a) { std::cout << a; }
inline void print(const int &a) { std::cout << a; }
inline void print(const unsigned &a) { std::cout << a; }
inline void print(const long &a) { std::cout << a; }
inline void print(const long long &a) { std::cout << a; }
inline void print(const unsigned long long &a) { std::cout << a; }
inline void print(const char &a) { std::cout << a; }
inline void print(const char a[]) { std::cout << a; }
inline void print(const float &a) { std::cout << a; }
inline void print(const double &a) { std::cout << a; }
inline void print(const long double &a) { std::cout << a; }
inline void print(const std::string &a) {
    for (auto &&i : a) print(i);
}
template <class T>
inline void print(const std::vector<T> &vec);
template <class T, size_t size>
inline void print(const std::array<T, size> &vec);
template <class T, class L>
inline void print(const std::pair<T, L> &p);
template <class T, size_t size>
inline void print(const T (&vec)[size]);
template <class T>
inline void print(const std::vector<T> &vec) {
    if (vec.empty()) return;
    print(vec[0]);
    for (auto i = vec.begin(); ++i != vec.end();) {
        std::cout << ' ';
        print(*i);
    }
}
template <class T>
inline void print(const std::deque<T> &vec) {
    if (vec.empty()) return;
    print(vec[0]);
    for (auto i = vec.begin(); ++i != vec.end();) {
        std::cout << ' ';
        print(*i);
    }
}
template <class T, size_t size>
inline void print(const std::array<T, size> &vec) {
    print(vec[0]);
    for (auto i = vec.begin(); ++i != vec.end();) {
        std::cout << ' ';
        print(*i);
    }
}
template <class T, class L>
inline void print(const std::pair<T, L> &p) {
    print(p.first);
    std::cout << ' ';
    print(p.second);
}
template <class T, size_t size>
inline void print(const T (&vec)[size]) {
    print(vec[0]);
    for (auto i = vec; ++i != end(vec);) {
        std::cout << ' ';
        print(*i);
    }
}
template <class T>
inline void print(const T &a) {
    std::cout << a;
}
inline void out() { std::cout << '\n'; }
template <class T>
inline void out(const T &t) {
    print(t);
    std::cout << '\n';
}
template <class Head, class... Tail>
inline void out(const Head &head, const Tail &...tail) {
    print(head);
    std::cout << ' ';
    out(tail...);
}
#define vec(type, name, ...) vector<type> name(__VA_ARGS__);
#define vv(type, name, h, ...) std::vector<std::vector<type>> name(h, std::vector<type>(__VA_ARGS__));
#define INT(...) int32_t __VA_ARGS__; in(__VA_ARGS__)
#define LL(...) int64_t __VA_ARGS__; in(__VA_ARGS__)
#define ULL(...) uint64_t __VA_ARGS__; in(__VA_ARGS__)
#define STR(...) std::string __VA_ARGS__; in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__; in(__VA_ARGS__)
#define LD(...) long double __VA_ARGS__; in(__VA_ARGS__)
#define VEC(type, name, size) std::vector<type> name(size); in(name)
#define VV(type, name, h, w) std::vector<std::vector<type>> name(h, std::vector<type>(w)); in(name)
template <class T>
ll sum(const T &a) {
    return accumulate(std::begin(a), std::end(a), 0LL);
}
template <class T>
ld dsum(const T &a) {
    return accumulate(std::begin(a), std::end(a), 0.0L);
}
template <class T>
auto min(const T &a) {
    return *min_element(std::begin(a), std::end(a));
}
template <class T>
auto max(const T &a) {
    return *max_element(std::begin(a), std::end(a));
}
template<typename T> T floor_div(const T n, const T d) {
    assert(d != 0);
    return n / d - static_cast<T>((n ^ d) < 0 && n % d != 0);
}
template<typename T> T ceil_div(const T n, const T d) {
    assert(d != 0);
    return n / d + static_cast<T>((n ^ d) >= 0 && n % d != 0);
}

using mint = modint998244353;

// エラトステネスの篩
struct Eratosthenes {
    // テーブル
    vector<bool> isprime;
    
    // 整数 i を割り切る最小の素数
    vector<int> minfactor;

    //メビウス関数
    //約数系包除に使用する
    //mobius[n] := nに同じ素因数が複数個ある => 0,  nの素因数が奇数個 => -1, 素因数が偶数個 => 1
    vector<int> mobius;

    // コンストラクタで篩を回す
    Eratosthenes(int N) : isprime(N+1, true),
                          minfactor(N+1, -1),
                          mobius(N+1, 1) {
        // 1 は予めふるい落としておく
        isprime[1] = false;
        minfactor[1] = 1;

        // 篩
        for (int p = 2; p <= N; ++p) {
            // すでに合成数であるものはスキップする
            if (!isprime[p]) continue;

            // p についての情報更新
            minfactor[p] = p;
            mobius[p] = -1;
            
            // p 以外の p の倍数から素数ラベルを剥奪
            for (int q = p * 2; q <= N; q += p) {
                // q は合成数なのでふるい落とす
                isprime[q] = false;
                
                // q は p で割り切れる旨を更新
                if (minfactor[q] == -1) minfactor[q] = p;
                if((q/p) % p == 0) mobius[q] = 0;
                else mobius[q] = -mobius[q];
            }
        }
    }

    // 高速素因数分解
    // pair (素因子, 指数) の vector を返す
    vector<pair<int,int>> factorize(int n) {
        vector<pair<int,int>> res;
        while (n > 1) {
            int p = minfactor[n];
            int exp = 0;

            // n で割り切れる限り割る
            while (minfactor[n] == p) {
                n /= p;
                ++exp;
            }
            res.emplace_back(p, exp);
        }
        return res;
    }

    // 高速約数列挙
    vector<int> divisors(int n) {
        vector<int> res({1});

        // n を素因数分解 (メンバ関数使用)
        auto pf = factorize(n);

        // 約数列挙
        for (auto p : pf) {
            int s = (int)res.size();
            for (int i = 0; i < s; ++i) {
                int v = 1;
                for (int j = 0; j < p.second; ++j) {
                    v *= p.first;
                    res.push_back(res[i] * v);
                }
            }
        }
        return res;
    }
};

vpi run_length(const vi& vec)
{
    int cn = 1;
    vpi res;
    rep(i,len(vec)-1) {
        if(vec[i] == vec[i+1]) cn++;
        else {
            res.eb(vec[i], cn);
            cn = 1;
        }
    }
    res.eb(vec.back(), cn);
    return res;
}

int main()
{
    INT(N);
    Eratosthenes er(N+1);
    vi primes;
    REP(i,2,N+1) if(er.isprime[i]) primes.pb(i);

    int siz = len(primes);
    vvpi ebs(siz);
    rep(i,siz) {
        int p = primes[i];
        vi tmp;
        ll base = 0;
        for(ll q=p;q<=N;q*=p) base += N/q;

        for(ll j=1;base/j!=0;j++) tmp.pb(base/j);
        //ebsをランレングス圧縮
        ebs[i] = run_length(tmp);
    }

    using ti = tuple<int,int,int>;
    vector<ti> events; //(eb, index, r-l)
    rep(i,siz) for(auto p : ebs[i]) events.eb(p.fi, i, p.se);
    events.eb(-1, -1, -1); //番兵
    sort(rall(events));
    
    mint ans = 0, proc = 1;
    vm array(siz,1);
    rep(i,len(events)-1) {
        auto [time, idx, width] = events[i];
        auto [ntime, nidx, nwidth] = events[i+1];
        //arrayの更新
        proc /= array[idx];
        {
            //ansの更新
            ans += mint(1) * time * width * proc;
        }
        array[idx] += width;
        proc *= array[idx];
    }

    out(ans.val());
}
0