Hướng dẫn giải của [2627 KS1] CHIAHET


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ác số từ 1 đến ~N~ chia hết cho đúng một trong hai số nguyên tố ~A~, ~B~ (chia hết cho cả hai thì không tính).

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

Duyệt từng ~x = 1..N~, kiểm tra ~x~ chia hết cho ~A~ và cho ~B~; đếm khi hai kết quả khác nhau. Nếu chỉ nộp sub này: đúng 38/40 test (2 test lớn bị quá thời gian).

Sub 2: Bao hàm – loại trừ — ~O(1)~

Số bội của ~A~ là ~\lfloor N/A \rfloor~, của ~B~ là ~\lfloor N/B \rfloor~, của cả hai là ~\lfloor N/\text{lcm}(A,B) \rfloor~. Đáp án = ~\lfloor N/A \rfloor + \lfloor N/B \rfloor - 2 \cdot \lfloor N/\text{lcm} \rfloor~. Trường hợp ~A = B~ thì lcm = ~A~, đáp án bằng 0 (đúng, vì số nào chia hết cho ~A~ cũng chia hết cho ~B~). Nếu chỉ nộp sub này: đúng 40/40 test.

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

main đọc ~N, A, B~; ~N \le 10^6~ gọi sub1, lớn hơn gọi sub2. Khi đi thi nên viết như vậy: sub sau có sai hoặc chưa kịp làm thì vẫn ăn điểm sub trước.

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

long long N, A, B;

// Sub 1: duyệt từng số từ 1 đến N, đếm số chia hết đúng một trong A, B — O(N), dùng khi N <= 10^6
void sub1() {
    long long cnt = 0;
    for (long long x = 1; x <= N; x++) {
        bool a = (x % A == 0), b = (x % B == 0);
        if (a != b) cnt++;
    }
    cout << cnt << "\n";
}

// Sub 2: bao hàm - loại trừ — O(1)
void sub2() {
    long long l = A / __gcd(A, B) * B;           // bội chung nhỏ nhất
    long long both = N / l;                      // chia hết cả hai
    cout << N / A + N / B - 2 * both << "\n";
}

int main() {
    freopen("CHIAHET.INP", "r", stdin);
    freopen("CHIAHET.OUT", "w", stdout);
    ios::sync_with_stdio(false); cin.tie(nullptr);
    cin >> N >> A >> B;
    if (N <= 1000000) 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.