Try   HackMD

Đề TS10 - BRVT - 2016: Editorial

Thông tin

Sau đây là lời giải của Kỳ thi Tuyển sinh 10 trường THPT chuyên Lê Quý Đôn tỉnh Bà Rịa - Vũng Tàu năm học 2016 - 2017.

Bạn đọc có thể nộp và chấm bài (test tự sinh) TẠI ĐÂY.

Chuẩn bị bởi team Logica, thuộc khuôn khổ dự án The Algitect (ALGI Project)

Bài 1:

Tóm tắt đề bài

Cho số nguyên dương

n.

Yêu cầu:

  • Cho biết
    n
    có phải số chẵn không
  • Tính các biểu thức sau:
    A=i=3n1i(i1)B=i=1n2i12i+1

Kiểm tra tính chẵn lẻ

Nếu

n chia hết cho
2
thì
n
chẵn, ngược lại
n
lẻ. Sử dụng phép toán
mod
để kiểm tra.

Độ phức tạp thời gian:

O(1)

Tính biểu thức A

Khởi gán

A=0. Duyệt qua mọi
i[3,n]
và cộng
1i(i1)
vào
A
.

Độ phức tạp thời gian:

O(n)

Tính biểu thức B

Khởi gán

B=0. Duyệt qua mọi
i[1,n]
và cộng
2i12i+1
vào
B
.

Độ phức tạp thời gian:

O(n)

Lưu ý: Vì bài toán liên quan đến số thực. Vậy nên cần sử dụng kiểu dữ liệu double hoặc long double để đảm bảo độ chính xác.

Độ phức tạp thời gian của cả bài toán là tổng độ phức tạp thời gian của từng yêu cầu.

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

int n;
double A, B;

int main() {
    cin >> n;
    for (int i = 3; i <= n; i++) {
        A += (double)1/((i-1)*i);
    }
    for (int i = 1; i <= n; i++) {
        B += (double)(2*i-1)/(2*i+1);
    }
    cout << (n & 1 ? "NO" : "YES") << '\n' << fixed << setprecision(2) << A << '\n' << B;
    return 0;
}

Bài 2

Tóm tắt đề bài

Cho

2 số nguyên dương
a
b
.

Yêu cầu:

  • Tối giản phân số
    ab
    .
  • Đếm số lượng số chia hết cho
    3
    trong đoạn
    [a,b]
    .

Tối giản phân số

Để tối giản

ab, ta chia
a
b
cho
UCLN(a,b)
.

C++ cung cấp sẵn hàm gcd() để tìm UCLN của hai số.

Độ phức tạp thời gian:

O(logmin(a,b))

Độ phức tạp của hàm gcd() trong C++ STL.

Đếm số lượng số chia hết cho 3 trong đoạn

Tip

Số lượng số chia hết cho

x từ
1
đến
n
là:
nx

Gọi

f(x) là số lượng số chia hết cho
3
trong đoạn
[1,x]
. Khi này,
f(x)=x3
.

Đáp án: %f(b) - f(a-1)$.

Độ phức tạp thời gian:

O(1)

Độ phức tạp thời gian của cả bài toán là tổng độ phức tạp thời gian của từng yêu cầu.

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

int main() {
    int a, b;
    cin >> a >> b;  
    
    int gcd = __gcd(a,b);
    cout << a / gcd << '/' << b / gcd << '\n' << b / 3 - (a - 1) / 3;
    
    return 0;
}

Bài 3:

Tóm tắt đề bài

Cho dãy số nguyên dương gồm

n phần tử
a1,a2,,an
.

  • Liệt kê các phần tử có dạng
    3k+2
    .
  • Tìm số có giá trị lớn nhất của dãy.
  • Tìm số có giá trị nhỏ nhất của dãy.

Liệt kê các phần tử có dạng
3k+2

Một số nguyên dương

x có dạng
3k+2
khi
x2(mod3)
hay
x20(mod3)
.

Nghĩa là

xmod3=0.

Do đó, ta duyệt qua mọi phần tử và in ra các phần tử thỏa mãn điều kiện trên.

Độ phức tạp thời gian:

O(n)

Tìm số có giá trị lớn nhất của dãy.

Gọi

fmax là giá trị lớn nhất của dãy.

  • Khởi gán
    fmax=
    .
  • Duyệt qua mọi
    i[1,n]
    , nếu
    fmax<ai
    thì gán
    fmax=ai
    .

Độ phức tạp thời gian:

O(n)

Tìm số có giá trị nhỏ nhất của dãy.

Gọi

fmin là giá trị lớn nhất của dãy.

  • Khởi gán
    fmin=
    .
  • Duyệt qua mọi
    i[1,n]
    , nếu
    fmin>ai
    thì gán
    fmin=ai
    .

Độ phức tạp thời gian:

O(n)

Độ phức tạp thời gian của cả bài toán là tổng độ phức tạp thời gian của từng yêu cầu.

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

int main() {
    int n;

    cin >> n;
    vector<int> a(n);
    for (auto& x : a) {
        cin >> x;
    }

    for (auto& x : a) {
        if ((x - 2) % 3 == 0) {
            cout << x << ' ';
        }
    }

    cout << '\n' << *max_element(a.begin(),a.end()) << '\n' << *min_element(a.begin(),a.end());
    
    return 0;
}

Bài 4

Tóm tắt đề bài

Cho dãy nguyên dương gồm

n phần tử
a1,a2,,an
.

Gọi

S1 là tổng các đồ vật từ
1
đến
k
S2
là tổng các đồ vật từ
k+1
đến
n
(1k<n)
.

Yêu cầu: Tìm cách chia sao cho

S1S2 lớn nhất.

Lời giải

Áp dụng prefix sum (mảng cộng dồn) cơ bản.

Gọi

fi=j=1iaj (tổng
i
số đầu tiên của mảng).

Khi này, ta có:

  • Tổng của các phần tử trong đoạn
    [1,k]
    S1=fk
    .
  • Tổng các phần tử trong đoạn
    [k+1,n]
    S2=fnfk
    .

Duyệt qua mọi

i[1,n) và tìm vị trí
i
để
fi(fnfi)
lớn nhất.

Độ phức tạp thời gian:

O(n)

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

int main() {
    int n;
    cin >> n;
    vector<long long> f(n+5,0);
    for (int i = 1; i <= n; i++) {
        int a;
        cin >> a;
        f[i] = f[i-1] + a;
    }
    
    long long ans = 0;
    array<int,2> f;
    
    for (int i = 1; i < n; i++) {
        long long v = f[i] * (f[n] - f[i]);
        if (ans < v) {
            ans = v;
            f = {f[i], f[n] - f[i]};
        }
    }
    
    cout << f[0] << ' ' << f[1];
    
    return 0;
}