---
# System prepended metadata

title: 'Đề TS10 - BRVT - 2017: Editorial'

---

# Đề TS10 - BRVT - 2017: Editorial

>[!Note] 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 2017 - 2018.
>
>**Bạn đọc có thể nộp và chấm bài (test tự sinh)** [TẠI ĐÂY](https://chuyentin-brvt.online/contest/algi_ts10_15_24).
>
>:::info
>Chuẩn bị bởi ==team Logica==, thuộc khuôn khổ dự án [**The Algitect (ALGI Project)**](https://www.facebook.com/algitect.project)
>:::

[toc]

## Bài 1

### Tóm tắt đề bài

Nhập vào số nguyên dương $N$. 

**Yêu cầu:** Tính kết quả các biểu thức sau:
- $A = \frac{1}{2} + \frac{2}{2^2} + \frac{3}{2^3} + \dots + \frac{N}{2^N}$
- $B = \frac{1 \times 2}{3 \times 4} + \frac{3 \times 4}{5 \times 6} + \frac{5 \times 6}{7 \times 8} + \dots + \frac{(2N - 3)(2N - 2)}{(2N - 1)2N}$

**Dữ liệu đảm bảo:** $2 \le N \le 100$.

### **Tính A**

Cho biến $i$ chạy vòng lặp từ $1$ đến $n$, cộng ==$\frac{i}{2^i}$== vào kết quả.

>[!Caution] Lưu ý
> Để tránh số quá lớn, ta nên lấy $i$ và chia liên tục cho $2$ thay vì tính $2^i$

**Độ phức tạp thời gian:** $O\left(n\right)$.

### **Tính B**

Cho biến $i$ chạy vòng lặp từ $2$ đến $n$, cộng ==$\frac{(2i - 3)\times(2i -2)}{2i}$== vào kết quả.

**Độ phức tạp thời gian:** $O\left(n\right)$.

### **Mã nguồn mẫu**

:::info
Độ 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.
:::

:::success 
:::spoiler Code

```cpp = 1
#include <bits/stdc++.h>
using namespace std;

int main() {
	int n;
	double A = 0, B = 0;

	cin >> n;
	for (int i = 1; i <= n; i++) {
		double ret = i;
		for (int j = 1; j <= i; j++) {
			ret /= 2;
        }

		A += ret;

		if (i >= 2) {
            B += (double)(2*i - 3)*(2*i - 2) / (2*i - 1) / (2*i);
        }
	}

	cout << fixed << setprecision(3) << A << "\n" << B;

	return 0;
}
```

:::

## Bài 2:

### Tóm tắt đề bài

Nhập vào $3$ số nguyên dương $a, b$ và $N$.

**Yêu cầu:**
- Tìm các **số nguyên tố** nằm trong đoạn $[a, b]$.
- Tìm **chữ số chẵn lớn nhất** của $N$.

**Dữ liệu đảm bảo:** $2 \le a < b \le 2 \times 10^5$ và $1 \le N \le 10^{18}$

### **Yêu cầu 1**

Duyệt qua các số từ $a$ đến $b$, kiểm tra tính nguyên tố của mỗi số bằng cách ==duyệt đến căn bậc hai== của số đó để tìm ước.

**Độ phức tạp thời gian:** $O \left( \sqrt a + \sqrt {a+1} + \dots + \sqrt b \right) = O\left( \sum_{i = a}^b \sqrt i \right)$.

### **Yêu cầu 2**

Duyệt qua các chữ số của $n$ để tìm ==chữ số chẵn lớn nhất==. Có thể thực hiện bằng cách không ngừng lấy chữ số tận cùng của $n$ là $n \bmod 10$, sau đó ta ==chia $n$ cho $10$== để xóa chữ số đó đi và tìm chữ số tiếp theo.

**Độ phức tạp thời gian:** $O\left( \log_{10} n \right)$.

### **Mã nguồn mẫu**

:::info
Độ 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.
:::

:::success 
:::spoiler Code
```cpp = 1
#include <bits/stdc++.h>
using namespace std;

bool isPrime(int x) {
	if (x < 2) {
        return 0;
    }
    
	for (int i = 2; i * i <= x; i++) {
		if (x % i == 0) {
			return 0;
        }
    }

	return 1;
}

int main() {
	int a, b;
    long long n;
	cin >> a >> b >> n;

	for (int i = a; i <= b; i++) {
		if (isPrime(i)) {
			cout << i << " ";
        }
    }

	int res = -1;
	do {
        if ((n % 10) % 2 == 0) {
            res = max(res, n % 10);
        }
    } while (n /= 10);

	cout << "\n" << res;

	return 0;
}
```
:::

## Bài 3:

### Tóm tắt đề bài

Cho dãy số nguyên gồm $N$ phần tử $a_1, a_2, \dots, a_N$ và số nguyên $X$.

**Yêu cầu:**
- Liệt kê các phần tử **dương** có dạng ==$5 \times k$ (với $k$ là số nguyên bất kỳ)== theo thứ tự ban đầu của dãy.
- Tìm **tích lớn nhất** của hai phần tử bất kỳ trong dãy (không trùng nhau).
- Sắp xếp dãy **tăng dần** và thực hiện chèn thêm một phần tử có giá trị $X$ vào dãy sao cho vẫn giữ nguyên tính chất **tăng dần** của dãy số.

**Dữ liệu đảm bảo:**
- $2 \le N \le 10^5$.
- $|a_i| \le 10^6$.
- $|X| \le 2 \times 10^6$

### **Yêu cầu 1**

>[!Tip] Nhận xét
>$$
>A_i = 5k \Leftrightarrow 5k = A_i \Leftrightarrow k = \frac {A_i}{5}
>$$
> Mà $k$ nguyên, do đó $A_i$ chia hết cho $5$, hay ==$A_i \bmod 5 = 0$==.

Như vậy, ta duyệt qua dãy và in ra các số thỏa mãn điều kiện trên.

**Độ phức tạp thời gian:** $O \left( n \right)$.

### **Yêu cầu 2**

>[!Tip] Nhận xét
> Dễ nhận thấy, ==hai số lớn nhất== của dãy sẽ tạo ra tích lớn nhất.
> :::danger
> **Lưu ý:** ==Hai số bé nhất (cùng âm)==, khi nhân vào sẽ tạo ra tích dương, và có thể lớn hơn tích của hai số lớn nhất.
> :::

Sắp xếp dãy tăng dần, ta có:
- Hai số lớn nhất là $A_N$ và $A_{N-1}$.
- Hai số nhỏ nhất là $A_1$ và $A_2$.

**Đáp án:** ==$\max(A_N \times A_{N-1}, A_1 \times A_{2})$==.

**Độ phức tạp thời gian:** $O(n \log n)$ do thao tác sắp xếp mảng.

### **Yêu cầu 3**

Để giữ nguyên tính chất tăng dần của dãy, ta cần chèn $x$ vào giữa hai vị trí ==$i$ và $i+1$== sao cho ==$A_i \le x \le A_{i+1}$==.

**Độ phức tạp thời gian:** $O(n)$.

### **Yêu cầu 4**

>[!Note]Nhận xét: 
>Chênh lệch giữa hai phần là lớn nhất khi một phần đạt tổng lớn nhất có thể và phần còn lại phải nhỏ nhất có thể.
>Dễ dàng nhận thấy,
>- Nếu $k \ge n-k$, ta nhóm ==$k$ phần tử lớn nhất== chung với nhau và ==$n-k$ phần tử nhỏ nhất== chung với nhau
>- Nếu $k \lt n-k$, ta nhóm ==$n-k$ phần tử lớn nhất== chung với nhau và ==$k$ phần tử nhỏ nhất== chung với nhau 

Có thể tìm nhanh tập các phần tử lớn nhất hoặc nhỏ nhát bằng cách sắp xếp lại dãy số. Để dễ thao tác, ta ==không thực sự chèn số vào==, mà ta sẽ duyệt qua dãy và in ra các số, nếu đúng vị trí của $x$ ta sẽ in ra $x$.

>[!Caution] Lưu ý
> Trường hợp $x$ lớn hơn tất cả các số trong dãy, ta phải thêm $x$ vào cuối.

**Độ phức tạp thời gian:** $O(n)$ vì dãy đã được sắp xếp sẵn ở yêu cầu trước.

### **Mã nguồn mẫu**

:::info
Độ 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.
:::

:::success 
:::spoiler Code

```cpp = 1
#include <bits/stdc++.h>
using namespace std;

const int N = 1e5;
int n, X, A[N+1];

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> A[i];
    }

	cin >> X;

	for (int i = 1; i <= n; i++) {
		if (A[i] > 0 && A[i] % 5 == 0) {
			cout << A[i] << " ";
        }
    }

	sort(A+1, A+1+n);
	cout << "\n" << max(1LL * A[1] * A[2], 1LL * A[n-1] * A[n]) << "\n";

	bool used = 0;
	for (int i = 1; i <= n; i++) {
		if (X <= A[i] && !used) {
			used = 1;
			cout << X << " ";
		}

		cout << A[i] << " ";
	}

	if (!used) {
        cout << X << " ";
    }

	return 0;
}

```

:::

## Bài 4:

### Tóm tắt đề bài

Có $N$ cây xanh xếp thành một hàng thẳng, lần lượt cách cổng trường THPT chuyên Lê Quý Đôn $a_1, a_2, \dots, a_N$. Bóng của chúng cũng thẳng hàng và bóng của cây thứ $i$ có chiều dài là $d_i$.

**Yêu cầu:** Tính tổng chiều dài của các bóng cây phủ trên đường.
> Lưu ý: Nếu có vùng bị phủ bóng bởi nhiều hơn một cây, chỉ xem vùng đó là một.

**Dữ liệu đảm bảo:** $1 \le N \le 10^5$, $0 < a_i \le 10^6$ và $0 < d_i \le 10^3$.

### Lời giải

>[!Tip] Mô hình hóa bài toán
> Dễ thấy, cây thứ $i$ cho ta vùng bóng ==$[a_i, a_i + d_i - 1]$==.
> Với mỗi vùng tương ứng của từng cây, ta cộng tất cả phần tử trong khoảng lên $1$.

Để cộng nhanh từng đoạn, ta áp dụng [**mảng hiệu**](https://wiki.vnoi.info/algo/data-structures/prefix-sum-and-difference-array.md).

**Độ phức tạp thời gian:** $O(n)$.

### **Mã nguồn mẫu**

:::success
:::spoiler Code

```cpp = 1
#include <bits/stdc++.h>
using namespace std;

const int N = 5e6;
int n, F[N+1];

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int x, y;
		cin >> x >> y;
		for (int j = x; j <= x+y-1; j++)
		    F[j]++;
	}

	int res = 0;
	for (int i = 1; i <= N; i++)
		if (F[i]) res++;

	cout << res;

	return 0;
}
```

:::