经典日期模拟题——AcwingAcWing 3489. 星期几
题目
已知 11 年 11 月 11 日是星期一。
现在给定一个日期,请你判断是星期几。
注意闰年的 22 月有 2929 天。
满足下面条件之一的是闰年:
- 年份是 44 的整数倍,而且不是 100100 的整数倍;
- 年份是 400400 的整数倍。
输入格式
输入包含多组测试数据。
每组数据占一行,包含一个整数 dd 表示日,一个字符串 mm 表示月,一个整数 yy 表示年。
月份 1∼121∼12,依次如下所示:
January, February, March, April, May, June, July, August, September, October, November, December
输出格式
每组数据输出一行结果,输出一个字符串表示给定日期是星期几。
周一至周日依次如下所示:
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
数据范围
1000≤y≤3000
给定日期保证合法。
每个输入最多包含 100 组数据。
输入样例:
9 October 2001
14 October 2001
输出样例:
Tuesday
Sunday
c++题解
#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
int months[13] = {
0, 31, 28, 31, 30, 31, 30, 31, 31,
30, 31, 30, 31
};
unordered_map<string, int> month_name = {
{"January", 1},
{"February", 2},
{"March", 3},
{"April", 4},
{"May", 5},
{"June", 6},
{"July", 7},
{"August", 8},
{"September", 9},
{"October", 10},
{"November", 11},
{"December", 12},
};
string week_name[7] = {
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
"Sunday"
};
int is_leap(int year)
{
return year % 4 == 0 && year % 100 || year % 400 == 0;
}
int get_days(int year, int month)
{
int s = months[month];
if (month == 2) return s + is_leap(year);
return s;
}
int main()
{
int d, m, y;
string str;
while (cin >> d >> str >> y)
{
m = month_name[str];
int i = 1, j = 1, k = 1;
int days = 0;
while (i < y || j < m || k < d)
{
k ++, days ++ ;
if (k > get_days(i, j))
{
k = 1;
j ++ ;
if (j > 12)
{
j = 1;
i ++ ;
}
}
}
cout << week_name[days % 7] << endl;
}
return 0;
}
Java题解
import java.util.HashMap;
import java.util.Scanner;
/**
* @see 模拟题 https://www.acwing.com/problem/content/3492/
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//思路:因为1年1月1日是星期一(已知)
//算出所求日期与此的差值,即为过的总天数
//因为不管在哪年哪月,一周都是7天,用总天数除以7的余数即为今天星期几
while (sc.hasNext()) {
HashMap<String, Integer> map = new HashMap<>();
map.put("January", 1);
map.put("February", 2);
map.put("March", 3);
map.put("April", 4);
map.put("May", 5);
map.put("June", 6);
map.put("July", 7);
map.put("August", 8);
map.put("September", 9);
map.put("October", 10);
map.put("November", 11);
map.put("December", 12);
String[] week = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
int[] months = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int day = sc.nextInt();
String month = sc.next();
int year = sc.nextInt();
//days表示从1年1月1日算起过了几天
int days = 0;
//算“年”过了多少天
for (int years = 1; years < year; years++) {
for (int i = 1; i <= 12; i++) {
days += months[i];
//特判闰年
if (i == 2) {
if (years % 4 == 0 && years % 100 != 0 || years % 400 == 0) {
days++;
}
}
}
}
//算“月”过了多少天
for(int m = 1; m < map.get(month); m++) {
days+=months[m];
if (m == 2) {
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
days++;
}
}
}
//已经加过了“年”,“月”;把“日”加上
days += day-1;
System.out.println(week[days % 7]);
}
}
}
python题解
解法一
data.weekday()
返回一个整数代表星期几,星期一为0,星期天为6。例如, date(2002, 12, 4).weekday() == 2,表示的是星期三。
data.isoweekday()
返回一个整数代表星期几,星期一为1,星期天为7。例如:date(2002, 12, 4).isoweekday() == 3,表示星期三。
参考资料:datetime — 基本日期和时间类型 — Python 3.10.0 文档
import datetime as dt
dates = []
while True:
try:
dates.append(list(input().split()))
except:
break
dic = {
'January': 1,'February':2,'March':3,'April':4,'May':5,'June':6,
'July':7,'August':8,'September':9,'October':10,'November':11,'December':12
}
weekday = {1: "Monday",2: 'Tuesday',3: 'Wednesday',4: 'Thursday',5: 'Friday',6: 'Saturday', 7: 'Sunday'}
for d, m, y in dates:
month = dic[m]
day = int(d)
year = int(y)
date=dt.date(year,month,day)
print(weekday[date.isoweekday()])
解法二:
公式
思路:
基姆拉尔森计算公式(Kim larsen calculation formula):W= (d+2m+3(m+1)/5+y+y/4-y/100+y/400+1)%7
w表示星期,w的取值范围是0~6,0代表星期日,1~6星期一到星期六
把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。
months = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
month_name = {"January": 1, "February": 2, "March": 3, "April": 4,
"May": 5, "June": 6, "July": 7, "August": 8,
"September": 9, "October": 10, "November": 11, "December": 12}
weeks = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
while True:
try:
d, m, y = input().split()
d = int(d)
m = str(m)
y = int(y)
month = month_name[m]
if month == 1 or month == 2:
month += 12
y -= 1
w = (d + 2 * month + 3 * (month + 1) // 5 + y + y // 4 - y // 100 + y // 400 + 1) % 7
print(weeks[w])
except EOFError:
break
解法三:
months = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
month_name = {"January": 1, "February": 2, "March": 3, "April": 4,
"May": 5, "June": 6, "July": 7, "August": 8,
"September": 9, "October": 10, "November": 11, "December": 12}
weeks = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
def is_leap(year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0 # 是否是闰年
def get_days(year, month):
s = months[month]
if month == 2:
return s + is_leap(year)
return s
while True:
try:
d, m, y = input().split()
d = int(d)
m = str(m)
y = int(y)
month = month_name[m]
days = 0
i, j, k = 1, 1, 1 # year, month, day
while i < y or j < month or k < d:
k += 1
days += 1
if k > get_days(i, j): # 到了下个月
k = 1
j += 1
if j > 12: # 跨年
j = 1
i += 1
print(weeks[days % 7])
except EOFError:
break
参考博客
AcWing 3489. 星期几(python + datatime ) - AcWing
datetime — 基本日期和时间类型 — Python 3.10.0 文档