| # | Bài tập | Điểm | Thời gian: | Giới hạn bộ nhớ |
|---|---|---|---|---|
| 1 | Google Code Jam 2017 - Ample Syrup | 25 | 1.0s | 1G |
| 2 | Google Code Jam 2017 - Core Training | 43 | 1.0s | 1G |
| 3 | Google Code Jam 2017 - Parenting Partnering | 32 | 1.0s | 1G |
Nhà bếp của Infinite House of Pancakes vừa nhận một đơn đặt một chồng gồm \(K\) chiếc bánh kếp! Đầu bếp hiện có \(N\) chiếc bánh, với \(N\ge K\). Mỗi chiếc bánh là một hình trụ; các bánh khác nhau có thể có bán kính và chiều cao khác nhau.
Là bếp phó, bạn phải chọn \(K\) trong số \(N\) chiếc bánh, bỏ những chiếc còn lại rồi xếp \(K\) chiếc đã chọn lên đĩa như sau. Trước tiên, lấy chiếc có bán kính lớn nhất và đặt một mặt tròn của nó xuống đĩa (nếu có nhiều chiếc cùng bán kính, có thể chọn bất kỳ chiếc nào). Sau đó đặt chiếc có bán kính lớn tiếp theo lên trên, cứ thế cho đến khi đủ \(K\) chiếc; tâm các mặt tròn phải nằm trên một đường thẳng vuông góc với đĩa, như hình minh họa:
Bạn biết thực khách chỉ yêu thích một thứ ngang với bánh kếp: si-rô! Ta muốn cực đại hóa tổng diện tích bề mặt bánh lộ ra trong chồng, vì càng nhiều bề mặt lộ ra thì càng có nhiều chỗ để rưới si-rô ngon tuyệt. Mọi phần của một chiếc bánh không tiếp xúc với chiếc bánh khác hoặc với đĩa đều được coi là lộ ra.
Nếu chọn tối ưu \(K\) chiếc bánh, tổng diện tích bề mặt lộ ra lớn nhất có thể đạt được là bao nhiêu?
Dòng đầu tiên chứa số bộ test \(T\). Mỗi bộ test bắt đầu bằng một dòng gồm hai số nguyên \(N\) và \(K\): tổng số bánh hiện có và số bánh trong chồng mà thực khách đặt. Tiếp theo là \(N\) dòng; dòng thứ \(i\) chứa hai số nguyên \(R_i\) và \(H_i\), lần lượt là bán kính và chiều cao của chiếc bánh thứ \(i\), tính bằng milimét.
Với mỗi bộ test, in một dòng Case #x: y, trong đó x là số thứ tự bộ test (bắt đầu từ 1) và y là tổng diện tích bề mặt lộ ra lớn nhất, tính bằng milimét vuông. y được chấp nhận nếu sai số tuyệt đối hoặc tương đối so với đáp án đúng không vượt quá \(10^{-6}\).
Test Set 1 (Visible): \(1\le N\le10\).
Test Set 2 (Hidden): \(1\le N\le1000\).
Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.
| Phân nhóm | Điểm Google Code Jam | Tỷ lệ điểm của bài |
|---|---|---|
| Test Set 1 | 9/25 | 36% |
| Test Set 2 | 16/25 | 64% |
Ví dụ 1
4
2 1
100 20
200 10
2 2
100 20
200 10
3 2
100 10
100 10
100 10
4 2
9 3
7 1
10 1
8 4
Case #1: 138230.076757951
Case #2: 150796.447372310
Case #3: 43982.297150257
Case #4: 625.176938064
Ở test 1, “chồng” chỉ có một chiếc bánh. Nếu dùng chiếc đầu tiên, diện tích lộ ra là \(\pi R_0^2+2\pi R_0H_0=14000\pi\,\mathrm{mm}^2\). Nếu dùng chiếc thứ hai, diện tích là \(44000\pi\,\mathrm{mm}^2\). Vì vậy dùng chiếc thứ hai tốt hơn.
Ở test 2, ta dùng cả hai chiếc bánh của test 1. Chiếc thứ nhất đóng góp mặt trên và mặt bên, tổng cộng \(14000\pi\,\mathrm{mm}^2\). Chiếc thứ hai đóng góp phần mặt trên không bị chiếc thứ nhất che cùng mặt bên, tổng cộng \(34000\pi\,\mathrm{mm}^2\). Tổng diện tích lộ ra là \(48000\pi\,\mathrm{mm}^2\).
Ở test 3, mọi chiếc bánh đều có bán kính 100 và chiều cao 10. Xếp hai chiếc lại tương đương một hình trụ mới có bán kính 100 và chiều cao 20, với diện tích lộ ra \(14000\pi\,\mathrm{mm}^2\).
Ở test 4, chồng tối ưu dùng hai chiếc bánh có bán kính 8 và 9.
Google Code Jam 2017, Vòng 1C, bài Ample Syrup.
Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.
Viết đề Code Jam rất khó, nên chúng tôi đã xây dựng một AI để nghĩ ra ý tưởng mới. Để AI sáng tạo nhất có thể, chúng tôi cấp cho nó \(N\) “lõi” khác nhau, mỗi lõi có một “tính cách” riêng. Tuy nhiên, cũng như con người, các lõi có thể mất tập trung, bị hỏng hoặc từ chối làm việc; lõi thứ \(i\) hoạt động đúng với xác suất thành công \(P_i\). Chỉ cần ít nhất \(K\) lõi hoạt động đúng thì AI hoạt động đúng. Nếu không, nó có lẽ sẽ hóa ác và nhốt chúng tôi trong một mê cung gồm những câu đố quái ác do chính nó thiết kế. Ai biết nó sẽ làm gì với Code Jam — có khi nó chỉ viết hàng loạt bài xác suất khó nhằn!
Để ngăn điều đó, chúng tôi dự định huấn luyện một hoặc nhiều lõi cho đáng tin cậy hơn. Ta có tổng cộng \(U\) “đơn vị huấn luyện”. Dùng \(X\) đơn vị cho lõi thứ \(i\) sẽ cộng \(X\) vào xác suất thành công của lõi đó. Có thể phân chia tùy ý, kể cả không cấp đơn vị nào cho một số lõi. Dĩ nhiên, xác suất thành công của một lõi không thể vượt quá 1.
Nếu phân bổ các đơn vị huấn luyện sao cho xác suất AI hoạt động đúng là lớn nhất, xác suất đó bằng bao nhiêu?
Dòng đầu tiên chứa số bộ test \(T\). Mỗi bộ test gồm ba dòng. Dòng đầu chứa hai số nguyên \(N\) và \(K\): tổng số lõi và số lõi tối thiểu phải thành công để AI hoạt động đúng. Dòng thứ hai chứa số hữu tỉ \(U\), số đơn vị huấn luyện. Dòng thứ ba chứa \(N\) số hữu tỉ \(P_i\); số thứ \(i\) là xác suất lõi thứ \(i\) hoạt động đúng. Tất cả các xác suất được cho với đúng bốn chữ số sau dấu thập phân.
Với mỗi bộ test, in Case #x: y, trong đó x là số thứ tự bộ test (bắt đầu từ 1) và y là xác suất AI hoạt động đúng khi phân bổ tối ưu. y được chấp nhận nếu sai số tuyệt đối hoặc tương đối không vượt quá \(10^{-6}\).
Bài có hai tập nhỏ và không có tập lớn. Trong cuộc thi gốc, phải giải Test Set 1 trước khi thử Test Set 2 và có thể thử lại mỗi tập với hình phạt thời gian.
Test Set 1 (Visible): \(K=N\); mọi lõi đều phải hoạt động đúng thì AI mới hoạt động đúng.
Test Set 2 (Visible): \(1\le K\le N\).
Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.
| Phân nhóm | Điểm Google Code Jam | Tỷ lệ điểm của bài |
|---|---|---|
| Test Set 1 | 15/43 | 34,88% |
| Test Set 2 | 28/43 | 65,12% |
Ví dụ 1
4
4 4
1.4000
0.5000 0.7000 0.8000 0.6000
2 2
1.0000
0.0000 0.0000
2 1
0.0000
0.9000 0.8000
2 1
0.1000
0.4000 0.5000
Case #1: 1.000000
Case #2: 0.250000
Case #3: 0.980000
Case #4: 0.760000
Hai test cuối không xuất hiện trong Test Set 1.
Ở test 1, số đơn vị huấn luyện đủ để nâng xác suất thành công của mọi lõi lên 1, nên AI chắc chắn hoạt động đúng.
Ở test 2, cả hai lõi đều phải thành công. Phương án tốt nhất là nâng mỗi lõi lên 0.5, cho xác suất \(0.5\times0.5=0.25\). Mọi cách khác đều kém hơn; chẳng hạn nâng một lõi lên 0.9 và lõi kia lên 0.1 chỉ cho \(0.9\times0.1=0.09\).
Ở test 3, không có đơn vị huấn luyện và chỉ cần ít nhất một trong hai lõi thành công. Xác suất cả hai cùng hỏng là \((1-0.9)(1-0.8)=0.02\), nên xác suất ít nhất một lõi thành công là \(1-0.02=0.98\).
Ở test 4, tối ưu là cấp toàn bộ đơn vị huấn luyện cho lõi thứ hai, khi đó xác suất ít nhất một lõi thành công là \(1-(0.4\times0.6)=0.76\). Cấp hết cho lõi đầu chỉ được 0.75, còn chia đều được 0.7525.
Google Code Jam 2017, Vòng 1C, bài Core Training.
Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.
Cameron và Jamie là bạn đời lâu năm và vừa trở thành cha mẹ! Chăm sóc em bé tuy đầy hào hứng nhưng cũng không ít thử thách. Vì cả hai đều có tư duy khoa học, họ quyết định áp dụng một cách tiếp cận khoa học cho việc chăm con.
Cameron và Jamie đang xây dựng lịch sinh hoạt hằng ngày và cần quyết định ai sẽ là người chính chăm em bé tại mỗi thời điểm. Họ luôn là những người bạn đời bình đẳng và không muốn thay đổi điều đó, nên mỗi người phải phụ trách đúng 12 giờ (720 phút) mỗi ngày.
Cameron có \(A_C\) hoạt động và Jamie có \(A_J\) hoạt động khác mà họ cần hoặc muốn tự mình thực hiện. Các hoạt động này diễn ra vào cùng thời điểm mỗi ngày. Không hoạt động nào của Cameron chồng lấn hoạt động của Jamie, nên luôn có ít nhất một người rảnh để chăm em bé.
Họ muốn lập một lịch chăm em bé thỏa mãn:
Ví dụ, giả sử Jamie có một hoạt động buổi sáng từ 9 đến 10 giờ, còn Cameron có một hoạt động buổi chiều từ 14 đến 15 giờ. Một lịch hợp lệ nhưng chưa tối ưu là Jamie chăm từ nửa đêm đến 6 giờ và từ 12 đến 18 giờ, còn Cameron chăm từ 6 đến 12 giờ và từ 18 giờ đến nửa đêm. Lịch này thỏa hai điều kiện đầu và có bốn lần đổi ca: lúc nửa đêm, 6 giờ, 12 giờ và 18 giờ. Một lần đổi ca tại nửa đêm được tính đúng một lần, không phải không lần hay hai lần.
Phương án tốt hơn là Cameron chăm từ nửa đêm đến 12 giờ, Jamie chăm từ 12 giờ đến nửa đêm. Lịch này cũng thỏa hai điều kiện đầu nhưng chỉ dùng hai lần đổi ca, và đó là số nhỏ nhất có thể.
Với danh sách hoạt động của Cameron và Jamie, hãy tìm số lần đổi ca nhỏ nhất trong một lịch hằng ngày.
Dòng đầu tiên chứa số bộ test \(T\). Mỗi bộ test bắt đầu bằng hai số nguyên \(A_C,A_J\), số hoạt động tương ứng của Cameron và Jamie. Tiếp theo có \(A_C+A_J\) dòng. \(A_C\) dòng đầu chứa \(C_i,D_i\): hoạt động thứ \(i\) của Cameron bắt đầu đúng \(C_i\) phút và kết thúc đúng \(D_i\) phút sau nửa đêm, kéo dài \(D_i-C_i\) phút. \(A_J\) dòng cuối chứa \(J_i,K_i\) với ý nghĩa tương tự cho Jamie. Không hoạt động nào kéo qua hai ngày; không có hai hoạt động chồng lấn, dù một hoạt động có thể kết thúc đúng lúc hoạt động khác bắt đầu và vẫn có thể đổi ca tại thời điểm đó.
Với mỗi bộ test, in Case #x: y, trong đó x là số thứ tự bộ test (bắt đầu từ 1) và y là số lần đổi ca nhỏ nhất.
Test Set 1 (Visible): \(0\le A_C,A_J\le2\) và \(1\le A_C+A_J\le2\).
Test Set 2 (Hidden): \(0\le A_C,A_J\le100\) và \(1\le A_C+A_J\le200\).
Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.
| Phân nhóm | Điểm Google Code Jam | Tỷ lệ điểm của bài |
|---|---|---|
| Test Set 1 | 12/32 | 37,5% |
| Test Set 2 | 20/32 | 62,5% |
Ví dụ 1
5
1 1
540 600
840 900
2 0
900 1260
180 540
1 1
1439 1440
0 1
2 2
0 1
1439 1440
1438 1439
1 2
3 4
0 10
1420 1440
90 100
550 600
900 950
100 150
1050 1400
Case #1: 2
Case #2: 4
Case #3: 2
Case #4: 4
Case #5: 6
Test 4 và 5 không xuất hiện trong Test Set 1.
Test 1 là tình huống được mô tả trong đề bài.
Ở test 2, Jamie phải chăm bé trong toàn bộ thời gian Cameron bận, rồi Cameron chăm toàn bộ thời gian còn lại. Lịch này có bốn lần đổi ca.
Ở test 3, có một lần đổi ca tại nửa đêm từ Cameron sang Jamie. Dù chia 1438 phút không có hoạt động còn lại thế nào, vẫn cần ít nhất một lần đổi từ Jamie về Cameron và không có lý do thêm lần đổi nào khác.
Ở test 4, các hoạt động sát nhau có thể thuộc cùng một người hoặc hai người khác nhau. Không đổi ca tại nửa đêm vì Cameron có hoạt động ngay trước lẫn ngay sau thời điểm đó. Tuy nhiên, lịch phải chèn thêm thời gian Cameron chăm giữa các hoạt động của Jamie, nên tổng cộng cần bốn lần đổi. Tối ưu là chèn một khoảng Cameron chăm dài 718 phút ở đâu đó giữa phút 2 và 1438; vị trí chính xác không ảnh hưởng số lần đổi, nên có nhiều lịch tối ưu.
Ở test 5, một lịch tối ưu có thể giao Cameron chăm trong các khoảng 100–200, 500–620 và 900–1400 phút.
Google Code Jam 2017, Vòng 1C, bài Parenting Partnering.
Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.