Try   HackMD

Đề TS10 - BRVT - 2019: 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 2019 - 2020.

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 một số nguyên dương

n.

Yêu cầu: Tính giá trị các biểu thức:

 A=13+24++n1n+1B=14×6+16×8+12n×(2n+2)

Dữ liệu đảm bảo:

2n100.

Tính biểu thức A

  • Duyệt
    i
    từ
    1
    đến
    n1
    , cộng vào đáp án
    ii+2
    .
  • Độ phức tạp thời gian:
    O(n)
    .

Tính biểu thức B

  • Duyệt
    i
    từ
    2
    đến
    n
    , cộng vào đáp án
    12i×(2i+2)
    .
  • Độ phức tạp thời gian:
    O(n)
    .

Lưu ý: Lưu đáp án bằng kiểu số thực.

Mã nguồn mẫu

Độ 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;
    
    double A = 0;
    for (int i = 1; i <= n - 1; i++) {
        A += (double)i / (i + 2);
    }

    double B = 0;
    for (int i = 2; i <= n; i++) {
        B += (double) 1 / (i * 2 * (i * 2 + 2));
    }
    
    cout << fixed << setprecision(5) << A << '\n' << B << '\n';

    return 0;
}

Bài 2:

Tóm tắt đề bài

Cho một số nguyên dương

n.

Yêu cầu:

  • Tìm chữ số tận cùng của
    3n
    .
  • Tính biểu thức:
    C=n×(n21)×(n24)5mod2019

Dữ liệu đảm bảo:

2n106.

Yêu cầu 1

Nhận xét

Những số

n với
nmod4
bằng nhau có cùng chữ số tận cùng.

Chứng minh

Xuất phát từ

30=1.

31=1×3=33mod10=3

32=3×3=99mod10=9

33=3×9=2727mod10=7

34=3×27=8181mod10=1

Ta lại quay về giá trị

30=1 ở ban đầu, dẫn đến sau đó chu kỳ gồm
1,3,9,7
này sẽ lặp đi lặp lại.

Như vậy, với những số

n
nmod4
bằng nhau thì chữ số tận cùng của
3n
tương ứng cũng bằng nhau.

Cụ thể, ta có các trường hợp:

  • nmod4=03nmod10=1
  • nmod4=13nmod10=3
  • nmod4=23nmod10=9
  • nmod4=33nmod10=7

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

O(1).

Yêu cầu 2

Ta không thể tính trực tiếp biểu thức

C rồi sau đó mới
mod
vì sẽ tràn dữ liệu.

Tính chất chia dư

Ta thừa nhận tính chất sau đây với

p=b×c:
abmodc=amodpb

Thay vào biểu thức

C với
p=2018×6
ta được
C=n×(n21)×(n24)modp6

Chú ý kết hợp modulo khi nhân để tránh tràn số

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

O(1)

Mã nguồn mẫu

Độ 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

Bài 3:

Tóm tắt đề bài

Nhập vào một dãy số nguyên dương gồm

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

Yêu cầu:

  • In ra các phần tử của dãy có chữ số tận cùng là
    0
    hoặc
    5
    .
  • In ra số lượng các phần tử của dãy có dạng
    4k+1
    (
    k
    là số nguyên).
  • In ra các phần tử của dãy là số chính phương (số nguyên dương
    x
    được gọi là số chính phương nếu tồn tại số nguyên
    k
    sao cho
    k2=x
    ).
  • In ra độ dài lớn nhất của dãy con xuất hiện trong dãy sao cho các phần tử (trừ phần tử đầu tiên) là bội số của phần tử đứng liền trước trong dãy con.

Dữ liệu đảm bảo:

2n105
1ai106
.

Yêu cầu 1

Duyệt qua từng giá trị trong dãy, lấy chữ số tận cùng của giá trị bằng cách chia dư cho

10. Nếu chữ số cuối cùng là
0
hoặc
5
thì in ra số đó.

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

O(n).

Yêu cầu 2

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

x có dạng
4k+1
khi
xmod4=1
.

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).

Yêu cầu 3

Kiểm tra số chính phương

Số chính phương là bình phương của một số nguyên.

Ta có thể kiểm tra một số

x có phải số chính phương hay không bằng cách lấy bình phương phần nguyên của
x
so sánh với
x
.
Nghĩa là,
x
chính phương khi và chỉ khi:
x2=x

Duyệt qua các phần tử trong mảng và thực hiện như trên. Có thể tính nhanh

x bằng hàm có sẵn trong thư viện của C++ là sqrt().

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

O(logn).

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

log.

Yêu cầu 4

Áp dụng quy hoạch động cơ bản.

  • Định nghĩa:
    dpx
    là độ dài dãy con dài nhất kết thúc tại giá trị
    x
    .
  • Khởi gán:
    dpx=1x
    (dãy con một phần tử cũng thỏa đề bài).
  • Công thức:
    dpx=max(dpy+1)
    với
    j
    là ước của
    i
    . Ta có thể duyệt qua các ước của
    i
    trong
    i
    .
  • Đáp án:
    max(dpi)
    với mọi giá trị
    i
    .

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

O(a1+a2++an)=O(i=1nai).

Mã nguồn mẫu

Độ 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;

const int N = 1e5 + 5, M = 1e6 + 5;
int n, a[N], cnt, dp[M], mx[M];

bool checkSqr(int x) {
    int t = sqrt(x);
    return t * t == x;
}

int main(void) {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        if (a[i] % 10 == 0 || a[i] % 10 == 5)
            cout << a[i] << ' ';
        if ((a[i] - 1) % 4 == 0)
            cnt++;
    }

    cout << '\n' << cnt << '\n';
    for (int i = 1; i <= n; i++)
        if (checkSqr(a[i]))
            cout << a[i] << ' ';

    int ans = 0;
    for (int i = 1; i <= n; i++) {
        dp[a[i]] = 1;
        for (int j = 1; j * j <= a[i]; j++) {
            if (a[i] % j == 0) {
                dp[a[i]] = max(dp[a[i]], mx[j] + 1);
                dp[a[i]] = max(dp[a[i]], mx[a[i] / j] + 1);
            }
        }

        mx[a[i]] = max(mx[a[i]], dp[a[i]]);
        ans = max(ans, dp[a[i]]);
    }

    cout << '\n' << ans;
    return 0;
}

Bài 4:

Tóm tắt đề bài

Cho một dãy số nguyên

a gồm
N
phần tử
a1,a2,...,aN
.

Yêu cầu: Cho biết số lượng các đoạn con có tổng giá trị các phần tử trong đoạn bằng

0.

Dữ liệu đảm bảo:

2N106
|ai|106
.

Lời giải

Nhận xét

Một đoạn

[l,r] có tổng bằng
0
, tức là:
al+al+1++ar=0

Giả sử ta có mảng cộng dồn
Si=a1+a2++ai
, biểu thức này tương đương:
SrSl1=0

Nếu ta cố định từng vị trí

r trên mảng, bài toán trở thành đếm số lượng số
l
thỏa mãn:

  • l<r
  • SrSl1=0
    hay
    Sl1=Sr

Sử dụng cấu trúc dữ liệu map để thực hiẹn việc này.

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

O(nlogn).

Mã nguồn mẫu

Code
#include <bits/stdc++.h>

using namespace std;
const long long N = 1e6;

long long n , ans;
long long a[N+5] , pre[N+5];
map<long long, long long> mp;

int main() {
    cin >> n;
    for(ll i = 1; i <= n; i++){
        cin >> a[i];
        pre[i] = pre[i-1] + a[i];
    }

    mp[0]++;
    for(ll i = 1; i <= n; i++){
        ans += mp[pre[i]];
        mp[pre[i]]++;
    }

    cout << ans;

    return 0;
}