結果
| 問題 | No.1728 [Cherry 3rd Tune] Bullet |
| コンテスト | |
| ユーザー |
hitonanode
|
| 提出日時 | 2021-10-29 22:28:58 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.89.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 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 27 |
ソースコード
#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';
}
hitonanode