题意
告诉你某年某月某日是星期一,满足是1号,或者11号,或者21号,让你找出第n个这样的星期一(满足是1号,或者11号,或者21号)
思路
以为O(10000)可以过的,结果超时,为什么不一上来就写成O(1)的。。。。
400年一个循环,预处理好再做
代码:
#define rep(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, n, m) for (int i = (n); i <= (m); i++)
typedef vector<int> vi;
int gao(int year1, int month1, int day1, int year2, int month2, int day2) {
int nd, nm, ny; //new_day, new_month, new_year
int od, om, oy; //old_day, oldmonth, old_year
nm = (month2 + 9) % 12;
ny = year2 - nm/10;
nd = 365*ny + ny/4 - ny/100 + ny/400 + (nm*306 + 5)/10 + (day2 - 1);
om = (month1 + 9) % 12;
oy = year1 - om/10;
od = 365*oy + oy/4 - oy/100 + oy/400 + (om*306 + 5)/10 + (day1 - 1);
return od - nd;
}
const int N = 800 * 36 + 5;
int e, tol;
int Y[N], M[N], D[N], V[N], pos[N];
int c[N][7];
int dx[3] = {1, 11, 21};
vi g[7];
void init() {
int x;
e = 0, tol = 36 * 400;
rep (i, 800) FOR (j, 1, 12) rep (k, 3) {
Y[e] = i, M[e] = j, D[e] = dx[k];
x = gao(i, j, dx[k], 0, 1, 1) % 7;
V[e] = x;
c[e][x]++;
pos[e] = SZ(g[x]), g[x].pb(e);
if (e != 0) rep (l, 7) c[e][l] += c[e - 1][l];
e++;
}
}
int T;
int y, m, d, n;
void solve() {
int y1 = y % 400, m1 = m, d1 = d, cnt, mod, p;
int id = 36 * y1 + 3 * (m1 - 1);
rep (k, 3) {
if (dx[k] == d1) break;
id++;
}
cnt = c[id + tol][V[id]] - c[id][V[id]];
p = n / cnt, cnt = n % cnt;
id = g[V[id]][pos[id] + cnt];
printf("%d %d %d\n", Y[id] - y1 + y + p * 400, M[id], D[id]);
}
int main() {
init();
scanf("%d", &T);
while (T--) {
scanf("%d %d %d %d", &y, &m, &d, &n);
n--;
solve();
}
return 0;
}