题意:
Gregorian Calendar格里高公历 就是现在广泛使用公历(西历),下面简称GC
GC平年有365天,闰年366天(2月多1天)
GC有12个月,各月的天数和现在的使用的西历一致
GC在1582年之前(不包括1582),若该年份能被4整除,则为闰年
GC在1582年之后(包括1582),判断闰年的标准(满足下面随便一个):
(1) 能被4整除,但不能被100整除;
(2) 能被400整除。
由于历史原因,GC规定1700年无条件为闰年
由于历史原因,GC规定1752年9月3日~13日共11天不存在,即1752年9月只有19天
GC的起始日期为 1年1月1号,该日为星期六
先把表打出来 最后只需相减就行。good和luck存的是从 1 year 1 month到 i year j month的和。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#define inf 0x3f3f3f3f
#define ll long long
#define mod 99991
using namespace std;
int good[100001][13];
int luck[100001][13];
int leap[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int ping[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int week = 6;
void assignMent(int i,int j){
if(j==1){
good[i][j]=good[i-1][12];
luck[i][j]=luck[i-1][12];
}
else{
good[i][j]=good[i][j-1];
luck[i][j]=luck[i][j-1];
}
if(week==0||week==6||week==1){
good[i][j]++;
}
}
void changeWeek(int i,int j,int day){
week = (week+day)%7;
if(week==0||week==6||week==1){
luck[i][j]++;
}
}
bool isOk(int i){
if(i < 1582){
if(i%4==0)return true;
return false;
}
if((i%4==0&&i%100!=0)||i%400==0||i==1700){
return true;
}
return false;
}
void cal_1_10000(){
memset(good,0,sizeof(good));
memset(luck,0,sizeof(luck));
for(int i = 1; i <= 10000; ++i){
bool flag = isOk(i);
for(int j = 1; j <= 12; ++j){
assignMent(i,j);
if(i==1752&&j==9){
changeWeek(i,j,19);
}
else if(flag){
changeWeek(i,j,leap[j]);
}
else{
changeWeek(i,j,ping[j]);
}
}
}
}
int main(){
cal_1_10000();
int T;
scanf("%d",&T);
int y1,m1,y2,m2;
while(T--){
scanf("%d%d%d%d",&y1,&m1,&y2,&m2);
if(y1 > y2){swap(y1,y2);swap(m1,m2);}
else if(y1==y2&&m1>m2){swap(m1,m2);}
int ans1,ans2;
if(m1 == 1){
ans1 = good[y2][m2]-good[y1-1][12];
ans2 = luck[y2][m2]-luck[y1-1][12];
}
else{
ans1 = good[y2][m2]-good[y1][m1-1];
ans2 = luck[y2][m2]-luck[y1][m1-1];
}
printf("%d %d\n",ans2,ans1);
}
return 0;
}