Solutions of Prison - MarisaOJ: Marisa Online Judge

Solutions of Prison

Select solution language

Write solution here.


User Avatar noice    Created at    14 likes

## Bài toán yêu cầu bạn tìm thời điểm ngày, tháng, năm sau $x$ ngày. ## Một hướng giải là tính xem bao nhiêu ngày đã trôi qua từ ngày đầu tiên (cho là bắt đầu từ 1/1/1) đến thời điểm hiện tại. Sau đó chuyển tổng số ngày đó thành số năm, số tháng, số ngày. Có thể giải như sau: - Tính số ngày đã qua từ ngày đầu năm. Ví dụ, nếu như là ngày 22/2/2025, thì tính số ngày đã qua từ 1/1/2025. Bạn cũng nên lưu ý [năm nhuận](https://vi.wikipedia.org/wiki/N%C4%83m_nhu%E1%BA%ADn#L%E1%BB%8Bch_Gregorius). - Tính số ngày còn lại từ ngày 1/1/1. Bạn có thể sử dụng [Nguyên lý Bao hàm - Loại trừ](https://vi.wikipedia.org/wiki/Nguy%C3%AAn_l%C3%BD_bao_h%C3%A0m-lo%E1%BA%A1i_tr%E1%BB%AB#%C4%90%E1%BA%BFm_s%E1%BB%91_nguy%C3%AAn) để tìm số ngày trong năm. Cụ thể hơn, gọi số ngày cần tìm là $d$, và xét trong $y$ năm: \begin{equation} d = 365 \cdot y + \lfloor \frac{y}{4} \rfloor + \lfloor \frac{y}{400} \rfloor\ - \lfloor\ \frac{y}{100} \rfloor\ \end{equation} - Từ đó, bạn tìm số năm thông qua tổng số ngày trong một lượng $400$ năm, vì các năm nhuận phân bố theo một chu kỳ. Bạn dễ dàng tìm được đáp án cho bài toán sau khi vét các ngày còn dư. ### Code tham khảo: ``` #include <bits/stdc++.h> using namespace std; #define int long long #define endl '\n' int dim[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; bool leap(int a) { return (a % 400 == 0 || (a % 4 == 0 && a % 100 != 0)); } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); int x, d, m, y; cin >> x >> d >> m >> y; int epoch = d; for (int i = 1; i < m; ++i) epoch += dim[i - 1]; if (leap(y) && m > 2) ++epoch; --y; epoch += y * 365 + y / 4 - y / 100 + y / 400; epoch += x; int Y = (epoch / 146097) * 400; epoch %= 146097; int yy = 1, D, M; while (epoch > 0) { int dd = (leap(yy) ? 366 : 365); if (epoch >= dd) { epoch -= dd; ++yy; continue; } dim[1] = (leap(yy) ? 29 : 28); D = epoch, M = 1; for (int i = 0; i < 12; ++i) { if (D <= dim[i]) { M = i + 1; break; } D -= dim[i]; } break; } cout << D << ' ' << M << ' ' << (Y + yy); }

User Avatar JoonYorigami    Created at    0 likes

Leap years happen on every year divisible by 4 except on years that are divisible by 100 but not divisible by 400. This means that the length of the cycle of leap years is 400 years (i.e year $y$ can be treated the same as $y+400$ or $y-400$)\ \ To calculate how many days are in 400 years, we have the equation\ $365\times400 + \lfloor \frac{400}{4} \rfloor - \lfloor \frac{400}{100} \rfloor + \lfloor \frac{400}{400} \rfloor$\ which gives us 146,097 days. We can then set our y and x as $(y := y + 400 * \lfloor \frac{x}{146097} \rfloor)$ and $(x := x \text{ % } 146097)$ respectively\ \ After this, it is guaranteed that $x < 146097$, this is small enough that we can simply iterate through the remaining days (beware of leap years)\ \ C++ Solution ```cpp #include <bits/stdc++.h> using namespace std; int main() { long long x,d,m,y; cin >> x >> d >> m >> y; // 400 years is 146,097 days y+=400*(x/146097); x%=146097; vector<int> monthdays({-1,31,28,31,30,31,30,31,31,30,31,30,31}); for(int i=0;i<x;i++) { d+=1; if(m==2) { //February if(y%4==0 && !(y%100==0 && y%400!=0)) { // leap year if(d>29) { m+=1; d=1; } } else { if(d>28) { m+=1; d=1; } } } else { if(d>monthdays[m]) { m+=1; d=1; } } if(m==13) { y+=1; m=1; } } cout << d << " " << m << " " << y; } ``` \ Python solution ```python monthdays=[-1,31,28,31,30,31,30,31,31,30,31,30,31] x,d,m,y=map(int,input().split()) y+=400*(x//146097) x%=146097 for _ in range(x): d+=1 if m==2: #February if y%4==0 and not (y%100==0 and y%400!=0): #Leap Year if d>29: m+=1 d=1 else: if d>28: m+=1 d=1 else: if d>monthdays[m]: m+=1 d=1 if m==13: y+=1 m=1 print(d,m,y) ```