ZOJ Problem Set - 3939 The Lucky Week

题目链接

(找规律+模拟)

题意:首先定义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;
}

猜你喜欢

转载自blog.csdn.net/weixin_41156591/article/details/80095750