题意:首先定义lucky-week是指:这天是周一而且是这个月的1,11,21号。给你t组测试样例,每组给出一行y,m,d,n,前三个是年月日,而且是满足lucky-week的第一个日期,要你输出你从这天开始第n个幸运周的日期。
题解:正常暴力做法被n限制了,那我们应该将n从1e9降下来,通过找到lucky-week关于年的循环规律,这里可以从电脑右下角的日历知道2001年的1月1号是lucky-week,而且考虑到闰年平年会有天数的差异导致答案的误差,我们我取最小避免平年闰年误差的值400年为周期,试着打一波从2001年到2401年的表可以发现,2401年的1月1日也是lucky-week,同时得到这400年中有2058个lucky-week(这里是不包括第2401年的),为了保险我们还可以打一波2001年到6001年的表,发现有20580个lucky-week(那就稳了),剩下的就是代码模拟了。
代码如下:
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
#define ll long long
const int maxn = 1e5 + 500;
int mon[15] = { 0,31,29,31,30,31,30,31,31,30,31,30,31 };
bool ok(int y) {//判断平年闰年
if (y % 400 == 0 || (y % 100 != 0 && y % 4 == 0))
return true;
return false;
}
void fun() {//打表找规律与判断答案是否正确
int s = 2001, t = 2401;
int sum = 0, cnt = 0;
for (int i = s; i < t; i++) {
if (ok(i)) mon[2] = 29;
else mon[2] = 28;
for(int j=1;j<=12;j++)
for (int k = 1; k <= mon[j]; k++) {
sum++;
if ((k == 1 || k == 11 || k == 21) && sum % 7 == 1) {
cnt++;
//cout << cnt << " " << i << " " << j << " " << k << endl;
}
}
}
cout << cnt << endl;
}
int main(){
//fun();
int t;
scanf("%d", &t);
while (t--) {
int y, m, d, n;
scanf("%d%d%d%d", &y, &m, &d, &n);
y += (n / 2058) * 400;
n %= 2058;
int i, j, k,sum=0,cnt=0;
if (cnt == n) { printf("%d %d %d\n", y, m, d); continue; }
if (ok(y)) mon[2] = 29;
else mon[2] = 28;
for (k = d; k <= mon[m]; k++) {//先把当前月的天数处理了
sum++;
if ((k == 1 || k == 11 || k == 21) && sum % 7 == 1) cnt++;
if (cnt == n)break;
}
if (cnt == n) { printf("%d %d %d\n", y, m, k); continue; }
for (j = m + 1; j <= 12; j++) {//再把当前年的月处理了
for (k = 1; k <= mon[j]; k++) {
sum++;
if ((k == 1 || k == 11 || k == 21) && sum % 7 == 1) cnt++;
if (cnt == n)break;
}
if (cnt == n)break;
}
if (cnt == n) { printf("%d %d %d\n", y, j, k); continue; }
for (i = y+1; ; i++) {//最后对年处理即一定能获得答案
if (ok(i)) mon[2] = 29;
else mon[2] = 28;
for (j = 1; j <= 12; j++) {
for (k = 1; k <= mon[j]; k++) {
sum++;
if ((k == 1 || k == 11 || k == 21) && sum % 7 == 1) cnt++;
if (cnt == n)break;
}
if (cnt == n)break;
}
if (cnt == n)break;
}
if (cnt == n) printf("%d %d %d\n", i, j, k);
}
return 0;
}