Không hỗ trợ Mobile

Chế độ luyện tập yêu cầu môi trường màn hình lớn để làm bài và chống gian lận hiệu quả. Vui lòng truy cập bằng máy tính (Desktop/Laptop) để tiếp tục thao tác.

Quay lại trang chủ

#1077 · Ghép hình chữ nhật - MAREC

Cho n que diêm có độ dài a_1, a_2,..., a_n.

Hãy đếm xem có thể ghép được bao nhiêu hình chữ nhật khác nhau từ các que diêm trên, biết rằng mỗi hình chữ nhật được tạo thành từ 4 que diêm.

Hai hình chữ nhật được coi là khác nhau nếu chúng không có cùng chiều dài và chiều rộng.

Dữ liệu vào

  • Dòng thứ nhất gồm một số nguyên dương n (4 \leq n \leq 1000).
  • Dòng thứ hai gồm n số nguyên dương a_1, a_2,..., a_n (1 \leq a_i \leq 1000)

Dữ liệu ra

In ra một số nguyên là số hình chữ nhật khác nhau có thể tạo thành.

BẢNG TỔNG QUAN KẾT QUẢ

# Tài khoản Kết suất Lúc nộp
1
1 ms 196 KB
477 Bytes
22/05/2023
16:36
2
1 ms 256 KB
381 Bytes
22/05/2023
18:53
3
1 ms 264 KB
510 Bytes
03/12/2022
23:03
4
Đ
1 ms 272 KB
610 Bytes
10/03/2023
14:08
5
1 ms 276 KB
687 Bytes
22/05/2023
18:17
6
1 ms 276 KB
687 Bytes
22/05/2023
18:17
7
1 ms 280 KB
687 Bytes
22/05/2023
18:19
8
1 ms 284 KB
623 Bytes
04/10/2023
20:22
9
1 ms 292 KB
844 Bytes
01/12/2022
19:41
10
1 ms 292 KB
928 Bytes
11/11/2023
11:52
11
V
1 ms 296 KB
569 Bytes
09/11/2025
00:42
12
P
1 ms 300 KB
538 Bytes
17/12/2025
17:05
13
T
Mã Hoàng Thái @2180606816
1 ms 304 KB
925 Bytes
07/03/2025
13:36
14
Đỗ Chí Thành @24800600886
1 ms 308 KB
810 Bytes
10/02/2025
20:28
15
N
Lê Thanh Như @2280602247
1 ms 308 KB
853 Bytes
23/07/2025
22:21
16
H
1 ms 324 KB
452 Bytes
05/12/2025
16:35
17
1 ms 340 KB
1348 Bytes
23/12/2025
13:36
18
Lê Duy Hải @2280600799
2 ms 164 KB
388 Bytes
23/01/2024
19:20
19
2 ms 220 KB
958 Bytes
29/06/2024
15:19
20
2 ms 260 KB
665 Bytes
14/05/2023
17:43

LỊCH SỬ CÁ NHÂN

Vui lòng đăng nhập để xem lịch sử làm bài của bạn.

THẢO LUẬN BÀI TOÁN

V
6 tháng trước

Hướng dẫn

Ta sẽ ví dụ với case mẫu ở hướng dẫn:

n = 9
2 4 5 2 2 4 5 4 3

Đầu tiên ta sẽ dùng mảng tần suất hoặc dùng hashmap hoặc ... để đếm số lượng giá trị a[i]

Giá trị a[i] | số lượng
     2       |    3
     3       |    1
     4       |    3
     5       |    2

Đơn giản với mảng tần suất:

#define MAX 10000

// Khởi tạo mảng tần suất
int b[MAX] = {0}; // Khởi tạo giá trị mặc định là 0

// Cách sử dụng:
// Dùng chính giá trị trong mảng a[i] để làm index
// Đảm bảo toàn bộ giá trị mảng là số nguyên dương và MAX >= giá trị max trong mảng
// Ví dụ sử dụng: b[a[i]]

Đầu tiên ta sẽ tạo 2 biến đếm riêng biệt để xử lý từng tình huống:

int dem_kq = 0; biến đếm kết quả (output)

int dem_2 = 0 biến đếm cho trường hợp hình CHỮ NHẬT.

Đầu tiên ta nhận ra rằng nếu a[i] có số lượng >= 4 thì chắc chắn sẽ tạo 1 hình vuông. Ta sẽ tạo 1 vòng for để tìm tới các a[i] có sl >= 4 và đếm. Đảm bảo không trùng lặp giá trị trước đó khi duyệt. (Tránh lặp thì ta có thể tạo mảng tần suất để làm mảng true/false hoặc đơn giản hơn là dùng kiểu dữ liệu bool với index chính là a[i]) Thì input trên ko có giá trị nào thoả mãn thế nên biến dem_kq = 0

Tiếp theo ta sẽ dùng biến đếm dem_2 để đếm các a[i] có số lượng >= 2

Lúc này dem_2 = 3 với các giá trị thoả mãn là 2,4,5 đều có sl >= 2

Sau đó ta sẽ dùng công thức (dem_2*(dem_2 - 1))/2

Rồi cộng dồn vào biến dem_kq: dem_kq += (dem_2*(dem_2 - 1))/2

Cuối cùng output là 3 cho case này!

Tại sao ta dùng đến công thức này? (dem_2*(dem_2 - 1))/2

Các cặp thoả mãn để tạo hình chữ nhật là: (2,4) (2,5) (4,5) = 3

Lập ma trận 3x3:

--2 4 5
2 X T T
4 X X T
5 X X X
X là không thoả mãn
T là thoả mãn

Thì bn học qua đại số tuyến tính thì nhận ra rằng các cặp thoả mãn là nửa tam giác trên.

Đầu tiên là n nhân n sẽ tính được toàn bộ hình vuông này ở đây là 3x3

Mà dòng cuối cùng không thoả mãn do cả dòng đều là X hết thế nên ta sẽ phải trừ đi 1 dòng.

=> n*(n - 1)

Lúc này ma trận còn:
--2 4 5
2 X T T
4 X X T

Ta nhận ra ngay rằng toàn bộ số lượng cặp thoả mãn = không thoả mãn thì ta sẽ chia 2 đi. Vậy ta sẽ hoàn thành công thức (n*(n-1))/2) để tính các cặp thoả mãn tạo nên hình chữ nhật với độ phức tạp o(1) cho việc tính toán và o(n) cho tìm a[i] có số lượng >= 2

Cuối cùng là cộng dồn dem_kq là xong bài toán :v Toàn bộ độ phức tạp là o(n)

Đọc đến đây chắc ae cũng mỏi mắt rồi nhỉ :v Mình viết lại để vững kiến thức. Ae nhớ tự cài đặt lại nhé :vv

Code mẫu cho ý tưởng trên:

#include <stdio.h>
#define MAX 10000

int main()
{
    int n;
    scanf("%d", &n);
    
    int a[n];
    int b[MAX] = {0}; // Mảng tần suất
    int c[MAX] = {0}; // Mảng true/false với 0 là false, 1 là true
    
    for(int i=0; i<n; i++)
    {
      scanf("%d", &a[i]);
      b[a[i]]++; // Cập nhật số lượng của phần tử a[i]
    }
    
    
    int dem_kq = 0;
    int dem_2 = 0;

    for(int i=0; i<n; i++)
    {
      if(c[a[i]] == 0)
      {
        if(b[a[i]] >= 4)
          dem_kq++;
        if(b[a[i]] >= 2)
          dem_2++;
        c[a[i]] = 1; // Khoá lại giá trị này để tránh bị trùng lặp khi duyệt
      }
    }
    
    printf("%d", dem_kq += (dem_2 * (dem_2-1))/2);
}
Vào thảo luận 0 Phản hồi
Viết code