結果
| 問題 |
No.2552 Not Coprime, Not Divisor
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-02-13 18:19:10 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 2,520 bytes |
| コンパイル時間 | 1,274 ms |
| コンパイル使用メモリ | 136,148 KB |
| 実行使用メモリ | 45,708 KB |
| 最終ジャッジ日時 | 2024-09-28 18:36:09 |
| 合計ジャッジ時間 | 18,329 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | -- * 3 |
| other | AC * 3 TLE * 5 -- * 17 |
ソースコード
#include <iostream>
#include <cassert>
#include <unordered_map>
#include <vector>
#include <random>
using namespace std;
using ll = long long;
int gcd (int x, int y) {
assert(x != 0 || y != 0);
x = max(x, -x), y = max(y, -y);
while (0 < y) {
int tmp = y;
y = x % y;
x = tmp;
}
return x;
}
auto naive (int N, vector<int>& A) {
ll ans = 0;
for (int i = 0; i < N; i++) {
for (int j = i+1; j < N; j++) {
int d = gcd(A[i], A[j]);
if (1 < d && d < A[i]) ans++;
}
}
return ans;
}
auto prime_factorization (ll N) {
assert(2 <= N);
vector<pair<ll, ll>> res;
int div = 2;
while (1LL*div*div <= N) {
if (N % div == 0) {
int count = 0;
while (N % div == 0) {
N /= div;
count++;
}
res.push_back( make_pair(1LL*div, 1LL*count) );
}
div++;
}
if (1 < N) res.push_back( make_pair(N, 1LL) );
return res;
}
auto generate_divisors (const vector<pair<ll, ll>>& factors) {
vector<pair<ll, int>> res;
auto dfs = [&](auto self, ll div, int count, int level) {
if (level == factors.size()) {
res.push_back(make_pair(div, count));
return;
}
ll prod = 1;
for (int i = 0; i <= factors[level].second; i++) {
self(self, div*prod, count+i, level+1);
prod *= factors[level].first;
}
};
dfs(dfs, 1, 0, 0);
return res;
}
auto solve (int N, vector<int>& A) {
ll ans = 0;
// 包除原理を用いて「(i, j)であって、i < jかつ1 < gcd(A[i], A[j])」を数え上げる。
// ついでに「(i, j)であって、i < jかつ1 < A[i]かつgcd(A[i], A[j]) = A[i]」も数え上げて、引く。
unordered_map<int, int> mp;
for (int j = N-1; 0 <= j; j--) {
if (A[j] == 1) {
continue;
}
auto f = prime_factorization(A[j]);
auto g = f;
for (auto& x : g) x.second = 1;
for (auto& x : generate_divisors(g)) {
if (x.first == 1) continue;
int sign = 1;
if (x.second % 2 == 0) sign = -1;
ans += sign * mp[x.first];
}
ans -= mp[A[j]];
for (auto& x : generate_divisors(f)) mp[x.first]++;
}
return ans;
}
int main () {
int N; cin >> N;
vector<int> A(N);
for (int i = 0; i < N; i++) A[i] = i+1;
cout << solve(N, A) << "\n";
}