結果

問題 No.8123 Calculated N !
コンテスト
ユーザー SnowBeenDiding
提出日時 2025-04-06 20:09:53
言語 C++23
(gcc 15.2.0 + boost 1.90.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
WA  
実行時間 -
コード長 5,265 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 6,204 ms
コンパイル使用メモリ 425,116 KB
実行使用メモリ 17,524 KB
最終ジャッジ日時 2026-07-08 13:16:37
合計ジャッジ時間 9,130 ms
ジャッジサーバーID
(参考情報)
judge3_0 / judge2_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample WA * 6
other AC * 1 WA * 15
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <atcoder/all>
#include <bits/stdc++.h>
#define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
using namespace atcoder;
using namespace std;

typedef long long ll;

struct LucyDP {
    ll prime_count;                 // 素数の個数
    ll prime_sum;                   // 素数の和
    ll min_prime_element_sum;       // 最小素因数の和
    map<ll, ll> prime_factor_count; // 素因数の個数

    LucyDP() : prime_count(0), prime_sum(0), min_prime_element_sum(0) {}

    void compute(ll n) {
        ll r = (ll)floor(sqrt(n));
        vector<ll> V;
        for (ll i = 1; i <= r; i++) {
            V.push_back(n / i);
        }
        for (ll i = V.back() - 1; i >= 1; i--) {
            V.push_back(i);
        }
        unordered_map<ll, int> idx;
        idx.reserve(V.size() * 2);
        for (int i = 0; i < (int)V.size(); i++) {
            idx[V[i]] = i;
        }
        vector<ll> S_arr(V.size()), C_arr(V.size());
        for (int i = 0; i < (int)V.size(); i++) {
            ll v = V[i];
            S_arr[i] = v * (v + 1) / 2 - 1;
            C_arr[i] = v - 1;
        }
        ll lpsum = 0;
        for (ll p = 2; p <= r; p++) {
            int pos_p = idx[p];
            int pos_pm1 = idx[p - 1];
            if (S_arr[pos_p] == S_arr[pos_pm1])
                continue;
            ll sp = S_arr[pos_pm1];
            ll cp = C_arr[pos_pm1];
            for (int i = 0; i < (int)V.size(); i++) {
                ll v = V[i];
                if (v < p * p)
                    break;
                int pos_v_div = idx[v / p];
                S_arr[i] -= p * (S_arr[pos_v_div] - sp);
                C_arr[i] -= (C_arr[pos_v_div] - cp);
                if (v == n) {
                    lpsum += p * (C_arr[pos_v_div] - cp);
                }
            }
        }
        int pos_n = idx[n];
        prime_count = C_arr[pos_n];
        prime_sum = S_arr[pos_n];
        min_prime_element_sum = lpsum + S_arr[pos_n];
    }

    void compute2(ll n) {
        ll r = (ll)floor(sqrt(n));
        vector<ll> V;
        for (ll i = 1; i <= r; i++) {
            V.push_back(n / i);
        }
        for (ll i = V.back() - 1; i >= 1; i--) {
            V.push_back(i);
        }
        unordered_map<ll, int> idx;
        idx.reserve(V.size() * 2);
        for (int i = 0; i < (int)V.size(); i++) {
            idx[V[i]] = i;
        }
        vector<ll> S_arr(V.size()), C_arr(V.size());
        for (int i = 0; i < (int)V.size(); i++) {
            ll v = V[i];
            S_arr[i] = v * (v + 1) / 2 - 1;
            C_arr[i] = v - 1;
        }
        ll lpsum = 0;
        for (ll p = 2; p <= r; p++) {
            int pos_p = idx[p];
            int pos_pm1 = idx[p - 1];
            if (S_arr[pos_p] == S_arr[pos_pm1])
                continue;
            ll sp = S_arr[pos_pm1];
            ll cp = C_arr[pos_pm1];
            for (int i = 0; i < (int)V.size(); i++) {
                ll v = V[i];
                if (v < p * p)
                    break;
                int pos_v_div = idx[v / p];
                S_arr[i] -= p * (S_arr[pos_v_div] - sp);
                C_arr[i] -= (C_arr[pos_v_div] - cp);
                if (v == n) {
                    lpsum += p * (C_arr[pos_v_div] - cp);
                }
            }
        }
        int pos_n = idx[n];
        prime_count = C_arr[pos_n];
        prime_sum = S_arr[pos_n];
        min_prime_element_sum = lpsum + S_arr[pos_n];
        vector<bool> isPrime(n + 1, true);
        isPrime[0] = isPrime[1] = false;
        for (ll i = 2; i * i <= n; i++) {
            if (isPrime[i]) {
                for (ll j = i * i; j <= n; j += i)
                    isPrime[j] = false;
            }
        }
        for (ll p = 2; p <= n; p++) {
            if (!isPrime[p])
                continue;
            ll cnt = 0;
            for (ll q = p; q <= n; q *= p) {
                cnt += n / q;
            }
            prime_factor_count[p] = cnt;
        }
    }
};

ll sqrt_ll(ll n) {
    // return floor(√n)
    auto check = [&](ll mid) {
        if (mid * mid <= n)
            return true;
        else
            return false;
    };
    auto binary = [&]() {
        ll L = 0, R = 3000000010;
        ll mid = (L + R) / 2;
        while (R - L > 1) {
            if (check(mid))
                L = mid;
            else
                R = mid;
            mid = (L + R) / 2;
        }
        return L;
    };
    ll ret = binary();
    return ret;
}

using mint = atcoder::modint1000000007;

vector<int> make_primes(ll n) {
    vector<int> prime;
    vector<bool> is_prime(n + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (ll i = 2; i <= n; i++) {
        if (is_prime[i]) {
            prime.push_back(i);
            for (ll j = i * 2; j <= n; j += i) {
                is_prime[j] = false;
            }
        }
    }
    return prime;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n;
    cin >> n;
    ll m = sqrt_ll(n);
    LucyDP lucy;
    lucy.compute(n);
    mint ans = 1;
    for (auto [p, cnt] : lucy.prime_factor_count) {
        ans *= (cnt + 1);
    }
    cout << ans.val() << endl;
}
0