# Hướng dẫn giải đề số 1 ## Bài 1 : Học - Ăn - Ngủ? ### Đề bài: Ta có thể hiểu bài toán là cho 3 chỉ số A , B , C sắp xếp lại theo thứ tự tăng dần. Ta có thể nhìn trong những test ví dụ. ### Cách làm Ta sẽ chia thành các trường hợp như sau: * Trường hợp 1 : *A* lớn nhất, *B* lớn 2, *C* lớn 3. * Trường hợp 2 : *A* lớn nhất, *C* lớn 2, *B* lớn 3. * Trường hợp 3 : *B* lớn nhất, *A* lớn 2, *C* lớn 3. * Trường hợp 4 : *B* lớn nhất, *C* lớn 2, *A* lớn 3. * Trường hợp 5 : *C* lớn nhất, *B* lớn 2, *A* lớn 3. * Trường hợp 6 : *C* lớn nhất, *A* lớn 2, *B* lớn 3. Ta có 6 trường hợp như trên, việc của ta chỉ là if-else sao cho thỏa mãn các trường hợp trên. ### Code Ở đây ta sẽ có 2 cách làm: **Cách 1:** ```c++ #include<bits/stdc++.h> using namespace std; int main(){ freopen("LAMGI.INP" , "r" , stdin); freopen("LAMGI.OUT" , "w" , stdout); int A , B , C; cin >> A >> B >> C; if(A > B && A > C){ cout << "Lam viec, "; if(B > C) cout << "Hoc, Ngu"; else cout << "Ngu, Hoc"; }else if(B > A && B > C){ cout << "Hoc, "; if(A > C) cout << "Lam viec, Ngu"; else cout << "Ngu, Lam viec"; }else{ cout << "Ngu, "; if(A > B) cout << "Lam viec, Hoc"; else cout << "Hoc, Lam viec"; } } ``` **Cách 2:** ```c++ #include <bits/stdc++.h> using namespace std; int main() { freopen("LAMGI.inp", "r", stdin); freopen("LAMGI.out", "w", stdout); ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); long long a, b, c; cin >> a >> b >> c; if (a > b && a > c && b > c) { cout << "Lam viec, Hoc, Ngu"; } else if (a > b && a > c && c > b) { cout << "Lam viec, Ngu, Hoc"; } else if (b > a && b > c && a > c) { cout << "Hoc, Lam viec, Ngu"; } else if (b > a && b > c && c > a) { cout << "Hoc, Ngu, Lam viec"; } else if (c > b && c > a && a > b) { cout << "Ngu, Lam viec, Hoc"; } else if (c > b && c > a && b > a) { cout << "Ngu, Hoc, Lam viec"; } } ``` Cả 2 cách đều có thể **AC** và đều thực hiện một việc là chia thành 6 trường hợp và in ra kết quả cho mỗi trường hợp khác nhau. ## Bài 2: Đồng Tiền ### Đề bài: Ở bài toán này, ta sẽ phân tích đề bài như sau. Tom muốn xếp hình tam giác có quy luật là: * Tầng 1 có 1 đồng tiền * Tầng 2 có 2 đồng tiền * ... * Tầng $k$ có $k$ đồng tiền. Gọi $S_k$ là tổng số đồng tiền phải sử dụng để xếp hình tam giác có $k$ tầng thì: $$S_k = 1 + 2 + 3 + .... + (k - 1) + k$$ $$=> S_k = \frac{k * (k + 1)}{2}$$ **Lưu ý:** $\frac{k * (k + 1)}{2}$ là tổng từ $1$ đến $k$. ### Cách làm: Ta sẽ đi tìm số $k$ lớn nhất có thể sao cho $S_k \le n$. Tức là tìm số $k$ lớn nhất sao cho tổng từ $1$ đến $k$ bé hơn hoặc bằng $n$. ### Code: Ta đều có thể **AC** bằng cách dùng for hoặc while. **Cách dùng While:** ```c++ #include<bits/stdc++.h> using namespace std; int main(){ freopen("triacoin.inp" , "r" , stdin); freopen("triacoin.out" , "w" , stdout); int n; cin >> n; int sum = 0 , k = 0; while(sum + (k + 1) <= n){ k++; sum = sum + k; } cout << k << endl; } ``` **Cách dùng for:** ```c++ #include<bits/stdc++.h> using namespace std; int main(){ freopen("triacoin.inp" , "r" , stdin); freopen("triacoin.out" , "w" , stdout); int n; cin >> n; int k = 0; for(int sum = 0 ; ; sum += k){ if(sum + (k + 1) > n) break; k++; } cout << k << endl; } ``` ## Bài 3: Mật khẩu ### Đề bài: Ở bài này, ta có thể tóm tắt lại bài toán là đếm số xâu có 4 chữ số mà trong đó chỉ có duy nhất 2 chữ số khác nhau (gọi là $x$ và $y$) sao cho cả $x$ và $y$ đều không nằm trong các số $x$ cho trước. ### Cách làm: Ta có thể duyệt qua từng cặp chữ số $(x , y)$ tương ứng với $2$ chữ số khác nhau, nếu cả 2 đều không nằm trong tập $x$ cho trước thì ta có thể cộng $6$ trường hợp vào với thứ tự như sau: * $xxyy$ * $xyxy$ * $yxyx$ * $yyxx$ * $xyyx$ * $yxxy$ Ví dụ, với cặp số $(0 , 1)$ thì ta có các số là: * $0011$ * $0101$ * $1010$ * $1100$ * $0110$ * $1001$ Thì mỗi cặp số như vậy sẽ có $6$ trường hợp thỏa mãn. ### Code: ```c++ #include<bits/stdc++.h> using namespace std; int a[10]; int main(){ freopen("matkhau.inp" , "r", stdin); freopen("matkhau.out" , "w" , stdout); int numTest; cin >> numTest; for(int T = 1 ; T <= numTest ; T++){ int n , kq = 0; cin >> n; for(int i = 1 ; i <= n ; i++) cin >> a[i]; for(int x = 0 ; x <= 9 ; x++){ for(int y = 0 ; y < x ; y++){ bool ok = true; for(int i = 1 ; i <= n ; i++) if(x == a[i] || y == a[i]){ ok = false; break; } if(ok == false) continue; kq += 6; } } cout << kq << endl; } } ``` **Lưu ý:** Bài toán có áp dụng việc có nhiều testcase nhỏ trong 1 test nên ta sẽ đọc **số lượng testcase** trước rồi lặp lại số lần chạy. **Giải thích code:** Có 2 điểm chính trong code này * Đầu tiên, với mỗi cặp $(x , y)$ ta sẽ kiểm tra việc có $x$ hoặc $y$ nằm trong tập $x$ hay không bằng cách duyệt qua tất cả các số cho trước rồi so sánh cho $x$ và $y$. Ngoài ra, ta có một biến bool **ok** để kiểm tra $(x , y)$ điều kiện. * Điều thứ hai, ta sẽ chỉ đếm các cặp $(x , y)$ với $(y < x)$ vì nếu không, tất cả các cặp sẽ bị đếm 2 lần. Ví dụ, nếu ta code như sau: ```c++ for(int x = 0 ; x <= 9 ; x++){ for(int y = 0 ; y <= 9 ; y++){ ``` Thì tất cả các cặp sẽ bị lặp lại $2$ lần vì 2 vòng for đếm $(x , y)$ và $(y , x)$.