Hướng dẫn giải của [Beginner Free Contest 01] C3


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Hướng dẫn giải

Đếm cặp ~(i, j)~ với ~i \le j~ sao cho ~a_i + a_j^2 = K~. Vì ~a_i \le 500~ nên có thể đếm theo giá trị.

Sub 1: Vét cạn — ~O(n^2)~, dùng khi ~n \le 5000~

Duyệt mọi cặp ~i \le j~ và kiểm tra trực tiếp. Nếu chỉ nộp sub này: đúng 3/10 test (các test lớn bị quá giờ).

Sub 2: Đếm theo giá trị — ~O(n)~

Duyệt ~j~ từ 1 đến ~n~, thêm ~a_j~ vào mảng đếm ~cnt~ trước (để cho phép ~i = j~), rồi cộng ~cnt[K - a_j^2]~ nếu giá trị đó nằm trong ~[1, 500]~. Đáp án có thể lớn nên dùng ~long long~. Nếu chỉ nộp sub này: đúng 10/10 test.

Chương trình hoàn chỉnh

~main~ đọc ~N, K~ và dãy, nếu ~N \le 5000~ gọi sub1, ngược lại gọi sub2.

#include <bits/stdc++.h>
using namespace std;

int n;
long long K;
long long a[100005];   // a[1..n]

// Sub 1: vet can O(n^2). Voi moi cap (i, j), i <= j, kiem tra truc tiep.
void sub1() {
    long long ans = 0;
    for (int j = 1; j <= n; j++)
        for (int i = 1; i <= j; i++)
            if (a[i] + a[j] * a[j] == K) ans++;
    cout << ans << "\n";
}

// Sub 2: O(n). Duyet j tu 1 den n, dem cac i <= j co a[i] = K - a[j]^2.
// cnt[v] = so chi so i da duyet co a[i] = v (a[i] <= 500).
void sub2() {
    vector<long long> cnt(501, 0);
    long long ans = 0;
    for (int j = 1; j <= n; j++) {
        cnt[a[j]]++;                       // them a[j] truoc (cho phep i = j)
        long long need = K - a[j] * a[j];  // gia tri a[i] can tim
        if (need >= 1 && need <= 500) ans += cnt[need];
    }
    cout << ans << "\n";
}

int main() {
    cin >> n >> K;
    for (int i = 1; i <= n; i++) cin >> a[i];
    if (n <= 5000) sub1();
    else sub2();
    return 0;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.