Problem
https://vn.spoj.com/problems/BLGEN
https://oj.vnoi.info/problem/BLGEN
Tế bào của một cá thể sinh vật ngoài hành tinh mới được phát hiện gồm rất nhiều gen, mỗi gen trong chuỗi gen của tế bào đều có số lượng nào đó các nucleotide (ký hiệu là nu). Các chuyên gia thường quan tâm chuỗi gen của mỗi cá thể dưới góc độ một chuỗi số lượng tương ứng các nu (gọi tắt là chuỗi nu), do đó chuỗi sẽ như là một dãy số nguyên dương đồng thời số số hạng của dãy này sẽ được gọi là độ dài của chuỗi. Mỗi gen được xem là đặc biệt nếu số nu của nó hoặc là bình phương của một số nguyên hoặc là lập phương của một số nguyên tố.
Để nghiên cứu khả năng biến đổi gen của loài sinh vật nói trên, các nhà khoa học xem xét hai mẫu chuỗi nu của hai cá thể và quan tâm đến mức độ “giống nhau” giữa chúng theo cách tìm ra chuỗi con chỉ gồm các gen đặc biệt mà cùng xuất hiện ở cả hai chuỗi nu (mỗi chuỗi con như vậy đều được gọi là chuỗi đặc trưng chung của hai chuỗi nu). Lưu ý rằng, chuỗi con của một chuỗi nu X, là chuỗi thu được từ X bằng cách giữ nguyên tất cả hoặc loại bỏ đi một số nào đó các gen mà vẫn giữ thứ tự xuất hiện trong chuỗi X.
Yêu cầu
Xác định độ dài lớn nhất L của chuỗi đặc trưng chung của hai chuỗi nu cho trước.
Dữ liệu
Cho trong file văn bản GEN.INP có:
- Dòng đầu ghi lần lượt các số hạng của chuỗi nu thứ nhất.
- Dòng tiếp theo ghi lần lượt các số hạng của chuỗi nu thứ hai.
- Tất cả các số hạng của hai chuỗi đều nguyên dương và không vượt quá 10^19
- Độ dài của mỗi chuỗi nu đều không vượt quá 1000.
Kết quả
Một số nguyên L tìm được.
Ví dụ
input
2 9 8 4 1 27 4 6
5 6 9 1 8 2 6 27 1 4
output
4
Giải thích: L = 4, một trong các chuỗi đăc trưng chung là: 9, 1, 27, 4
Ràng buộc
60% số test ứng với 60% số điểm của bài ứng với tình huống độ dài của hai chuỗi nu không vượt quá 255 và giá trị của mỗi số hạng đều không vượt quá 10^6.
Tutorial
Do tôi code C++ nên bài này khó khăn ở chỗ nhập dữ liệu, còn thuật toán thì khá đơn giản chỉ là tìm ra hai chuỗi đặc trưng của A và B sau đó tìm dãy con chung dài nhất bằng QHĐ đơn giản.
Để tìm ra chuỗi đặc trưng của mỗi chuỗi thì ta sẽ xét từng kí tự trong chuỗi đó, tính căn bậc ba bằng chặt nhị phân cho chắc ăn vì nếu dùng pow(x,1/3)
với số lớn như vậy (10^19)
thì không an toàn, chặt nhị phân giá trị căn bậc ba trong khoảng từ 1 -> căn bậc ba của 10^19 thôi.
Còn kiểm tra số nguyên tố thì có thể xử lí trong O(sqrt(X))
với X
lớn nhất là căn bậc ba của 10^19
(cỡ khoảng 1500), khá nhỏ với dữ kiện độ dài mỗi chuỗi chưa đến 1000 (giải thích : trong trường hợp xấu nhất thì tất cả đều lớn, mỗi số dài 20 thì số lượng các số chưa đến 50, số lượng số cả hai chuỗi chưa đến 100). Có thể tối ưu hơn bằng thuật kiểm tra số nguyên tố sau : xét các số trong khoảng 2->căn(X)
, nếu X chia hết cho các số có dạng 6k+1 và 6k+5 thì nó không nguyên tố.
Lưu ý cho bài này: Dùng unsign long long để đảm bảo không tràn số. Giữa các số trong input có thể có nhiều khoảng trắng nên cần kiểm tra điều này (dòng đầu trong hàm check(llu x)
của code)
Submission
Nếu bạn thấy bài viết này hay, hãy share bài viết này cho mọi người nhé 😉.
Share this post →