题目链接:http://icpc.moe/onlinejudge/showProblem.do?problemId=5711
此题是浙江省第13届省赛的D题,比赛的时候小编一开始开的就是这个题,因为自己也有算天数差的模板,想也没想直接粘过来用,不管是怎么算都是TLE,后来才发现10^9的数据使肯定要爆的,必须得着周期才能算出来,在天数月份年数平闰年和星期数总体的周期是400(可能有人要问小编为什么加上星期数的周期还是400呢?平闰年的总体周期为400不难理解,但是如果你去计算你会发现每过400年的天数刚刚好也是7的倍数,这个当时在比赛的时候小编也专门开了一个草稿件去计算过,不懂得同学也可以直接去试试),因为我们的时间最小只能达到1753,所以我们先预处理1753的后门400年的情况,这样我们就可以再对应到我们算的那个时间,就可以处理出这个时间。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long ll; struct point { int year, month, day; int cnt; point (int year = 0, int month = 0, int day = 0, int cnt = 0): year(year), month(month), day(day), cnt(cnt){} }; point a[10000]; int n; int cnt; int d1[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int d2[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; bool check(int x) { if (x % 400 == 0 || (x % 4 == 0 && x % 100 != 0)) return true; return false; } void init() { cnt = 1; int day = 1; for (int i = 1753; i <= 1753 + 399; i++) { bool flag = false; flag = check(i); for (int j = 1; j <= 12; j++){ int tmp = (flag == 1 ? d2[j] : d1[j]); while (day <= tmp){ if (day == 1 || day == 11 || day == 21) { a[cnt] = point(i, j, day, cnt); cnt++; } day += 7; } day -= tmp; } } } int main() { init(); cnt--; int t; scanf("%d", &t); while (t--){ int y, m, d; scanf("%d%d%d", &y, &m ,&d); int n; scanf("%d", &n); n--; int ind = n / cnt; int tmp = n - ind * cnt; int mid = 0; while (y >= 1753 + 400) { y -= 400; mid++; } //printf("y = %d mid = %d tmp = %d\n", y, mid, tmp); ll t1 = 0, t2 = 0, t3 = 0; for (int i = 1; i <= cnt; i++){ if (y == a[i].year && m == a[i].month && d == a[i].day){ int g = i; g += tmp; while (g > cnt){ g -= cnt; mid++; } t1 = (ll)a[g].year + (ll)(mid + ind) * 400; t2 = (ll)a[g].month; t3 = (ll)a[g].day; break; } } printf("%lld %lld %lld\n", t1, t2, t3); } return 0; }