結果

問題 No.2552 Not Coprime, Not Divisor
ユーザー InTheBloomInTheBloom
提出日時 2024-02-13 18:19:10
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 2,520 bytes
コンパイル時間 1,573 ms
コンパイル使用メモリ 136,784 KB
実行使用メモリ 52,476 KB
最終ジャッジ日時 2024-02-13 18:19:28
合計ジャッジ時間 8,445 ms
ジャッジサーバーID
(参考情報)
judge14 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1,333 ms
24,504 KB
testcase_01 TLE -
testcase_02 AC 1,107 ms
24,128 KB
testcase_03 TLE -
testcase_04 TLE -
testcase_05 AC 308 ms
10,060 KB
testcase_06 TLE -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#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";
}
0