結果

問題 No.1728 [Cherry 3rd Tune] Bullet
ユーザー hitonanodehitonanode
提出日時 2021-10-29 22:28:58
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 24 ms / 2,000 ms
コード長 3,024 bytes
コンパイル時間 1,634 ms
コンパイル使用メモリ 122,532 KB
実行使用メモリ 7,968 KB
最終ジャッジ日時 2024-10-07 12:05:03
合計ジャッジ時間 3,074 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 10 ms
7,756 KB
testcase_01 AC 11 ms
7,884 KB
testcase_02 AC 11 ms
7,888 KB
testcase_03 AC 11 ms
7,884 KB
testcase_04 AC 11 ms
7,884 KB
testcase_05 AC 11 ms
7,880 KB
testcase_06 AC 11 ms
7,760 KB
testcase_07 AC 11 ms
7,884 KB
testcase_08 AC 13 ms
7,884 KB
testcase_09 AC 15 ms
7,968 KB
testcase_10 AC 15 ms
7,884 KB
testcase_11 AC 13 ms
7,808 KB
testcase_12 AC 14 ms
7,752 KB
testcase_13 AC 15 ms
7,752 KB
testcase_14 AC 13 ms
7,756 KB
testcase_15 AC 16 ms
7,880 KB
testcase_16 AC 13 ms
7,884 KB
testcase_17 AC 14 ms
7,764 KB
testcase_18 AC 14 ms
7,760 KB
testcase_19 AC 15 ms
7,756 KB
testcase_20 AC 13 ms
7,884 KB
testcase_21 AC 15 ms
7,880 KB
testcase_22 AC 14 ms
7,880 KB
testcase_23 AC 24 ms
7,808 KB
testcase_24 AC 22 ms
7,884 KB
testcase_25 AC 17 ms
7,888 KB
testcase_26 AC 11 ms
7,808 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <algorithm>
#include <cassert>
#include <iostream>
#include <map>
#include <vector>
using namespace std;


// Linear sieve algorithm for fast prime factorization
// Complexity: O(N) time, O(N) space:
// - MAXN = 10^7:  ~44 MB,  80~100 ms (Codeforces / AtCoder GCC, C++17)
// - MAXN = 10^8: ~435 MB, 810~980 ms (Codeforces / AtCoder GCC, C++17)
// Reference:
// [1] D. Gries, J. Misra, "A Linear Sieve Algorithm for Finding Prime Numbers,"
//     Communications of the ACM, 21(12), 999-1003, 1978.
// - https://cp-algorithms.com/algebra/prime-sieve-linear.html
// - https://37zigen.com/linear-sieve/
struct Sieve {
    std::vector<int> min_factor;
    std::vector<int> primes;
    Sieve(int MAXN) : min_factor(MAXN + 1) {
        for (int d = 2; d <= MAXN; d++) {
            if (!min_factor[d]) {
                min_factor[d] = d;
                primes.emplace_back(d);
            }
            for (const auto &p : primes) {
                if (p > min_factor[d] or d * p > MAXN) break;
                min_factor[d * p] = p;
            }
        }
    }
    // Prime factorization for 1 <= x <= MAXN^2
    // Complexity: O(log x)           (x <= MAXN)
    //             O(MAXN / log MAXN) (MAXN < x <= MAXN^2)
    template <typename T> std::map<T, int> factorize(T x) const {
        std::map<T, int> ret;
        assert(x > 0 and x <= ((long long)min_factor.size() - 1) * ((long long)min_factor.size() - 1));
        for (const auto &p : primes) {
            if (x < T(min_factor.size())) break;
            while (!(x % p)) x /= p, ret[p]++;
        }
        if (x >= T(min_factor.size())) ret[x]++, x = 1;
        while (x > 1) ret[min_factor[x]]++, x /= min_factor[x];
        return ret;
    }
    // Enumerate divisors of 1 <= x <= MAXN^2
    // Be careful of highly composite numbers https://oeis.org/A002182/list https://gist.github.com/dario2994/fb4713f252ca86c1254d#file-list-txt
    // (n, (# of div. of n)): 45360->100, 735134400(<1e9)->1344, 963761198400(<1e12)->6720
    template <typename T> std::vector<T> divisors(T x) const {
        std::vector<T> ret{1};
        for (const auto p : factorize(x)) {
            int n = ret.size();
            for (int i = 0; i < n; i++) {
                for (T a = 1, d = 1; d <= p.second; d++) {
                    a *= p.first;
                    ret.push_back(ret[i] * a);
                }
            }
        }
        return ret; // NOT sorted
    }
};
Sieve sieve((1 << 20));

#include <atcoder/modint>
using mint = atcoder::modint1000000007;

mint solve() {
    int N, C;
    cin >> N >> C;
    mint ret = mint(C).pow(N) * N;
    map<int, int> mp;
    for (auto d : sieve.divisors(N)) mp[d] = N / d;

    for (auto [p, deg] : sieve.factorize(N)) {
        for (auto [a, b] : mp) {
            if (a % p == 0) mp[a / p] -= mp[a];
        }
    }
    for (auto [d, val] : mp) {
        ret += mint(C).pow(d * 2) * val;
    }
    return ret / (N * 2);
}

int main() {
    int T;
    cin >> T;
    while (T--) cout << solve().val() << '\n';
}
0