[蓝桥杯2015初赛]星系炸弹
题目描述
在X星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。
每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸。
有一个贝塔炸弹,a年b月c日放置,定时为n天,请你计算它爆炸的准确日期。
输入
输入存在多组数据,每组数据输入一行,每一行输入四个正整数a,b,c,n
输入保证日期在1000-01-01到2020-01-01之间,且日期合法。
n不超过1000
输出
请填写该日期,格式为 yyyy-mm-dd 即4位年份2位月份2位日期。比如:2015-02-19
请严格按照格式书写。不能出现其它文字或符号。
样例输入
2015 1 1 15 2014 11 9 1000 |
分析
先单位统一,将初始的日期化为天数,然后加上流逝的天数,再将该天数化为日期。注意闰年的特判。(公元元年为 公元 1 年)
# include <iostream>
int month[15] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool run(int num) {
return (num % 4 == 0 && num % 100 !=0) || num % 400 == 0;
}
int main() {
int y1;
int m1;
int d1;
int pa;
while (std::cin >> y1 >> m1 >> d1 >> pa) {
int s = 0;
for (int i=1; i<y1; i++) {
if (run(i)) {
s += 366;
} else {
s += 365;
}
}
if (run(y1)) {
month[2] = 29;
} else {
month[2] = 28;
}
for (int i=0; i<m1; i++) {
s += month[i];
}
s += d1 + pa;
int y2;
int m2;
int d2;
for (y2=1; ; y2++) {
if (run(y2)) {
if (s <= 366) {
break;
} else {
s -= 366;
}
} else {
if (s <= 365) {
break;
} else {
s -= 365;
}
}
}
if (run(y2)) {
month[2] = 29;
} else {
month[2] = 28;
}
for (m2=1; ; m2++) {
if (s <= month[m2]) {
d2 = s;
break;
} else {
s -= month[m2];
}
}
std::cout << y2 << '-';
if (m2 / 10 == 0) {
std::cout << '0';
}
std::cout << m2 << "-";
if (d2 / 10 == 0) {
std::cout << '0';
}
std::cout << d2 << "\n";
}
return 0;
}
[蓝桥杯2017初赛]日期问题
题目描述
小明正在整理一批历史文献。这些历史文献中出现了很多日期。
小明知道这些日期都在1960年1月1日至2059年12月31日。
令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。
更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?
输入
一个日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)
输出
输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。
多个日期按从早到晚排列。
样例输入
02/03/04 |
样例输出
2002-03-04 2004-02-03 2004-03-02 |
分析
日期有 年/月/日 、月/日/年 、日/月/年 这三种方式,其中年份可能是20世纪,也可能是21世纪,因此共6种情况。先排序、去重,再判断每一种日期是否合理,合理则按照题目要求输出。
# include <iostream>
# include <vector>
# include <algorithm>
struct date {
int year;
int month;
int day;
bool operator < (date rhs) {
if (year < rhs.year) {
return true;
} else if (year == rhs.year) {
if (month < rhs.month) {
return true;
} else if (month == rhs.month) {
return day < rhs.day;
} else {
return false;
}
} else {
return false;
}
}
bool operator == (date rhs) {
return year == rhs.year && month == rhs.month && day == rhs.day;
}
};
bool run(int num) {
return (num % 4 ==0 && num % 100 != 0) || num % 400 == 0;
}
bool is(date t) {
if (t.year < 1960 || t.year > 2059) {
return false;
}
int mon[14] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (run(t.year)) {
mon[2] = 29;
}
if (t.month > 12 || t.month < 1) {
return false;
}
if (t.day <= mon[t.month] && t.day > 0) {
return true;
} else {
return false;
}
}
int main() {
int a, b, c;
char ct;
std::cin >> a >> ct >> b >> ct >> c;
std::vector<date> d;
d.resize(6);
d[0].year = 2000 + a;
d[0].month = b;
d[0].day = c;
d[1].year = 2000 + c;
d[1].month = a;
d[1].day= b;
d[2].year = 2000 + c;
d[2].month = b;
d[2].day= a;
d[3].year = 1900 + a;
d[3].month = b;
d[3].day = c;
d[4].year = 1900 + c;
d[4].month = a;
d[4].day= b;
d[5].year = 1900 + c;
d[5].month = b;
d[5].day= a;
std::sort(d.begin(), d.end());
d.erase(std::unique(d.begin(), d.end()), d.end());
for (int i=0; i<d.size(); i++) {
if (is(d[i])) {
std::cout << d[i].year << "-";
if (0 == d[i].month / 10) {
std::cout << 0;
}
std::cout << d[i].month << "-";
if (0 == d[i].day / 10) {
std::cout << 0;
}
std::cout << d[i].day << "\n";
}
}
return 0;
}
[蓝桥杯2018初赛]星期一
题目描述
整个20世纪(1901年1月1日至2000年12月31日之间),一共有多少个星期一?
(不要告诉我你不知道今天是星期几)
输出
输出一个整数表示答案 |
分析
如果从现在的时间倒着推回 公元1月1日 , 那结果是星期一, 但是有些手机上面的日历是星期六 。由于1582年时日历对春分的记载和地球公转到春分点的实际时间相差十天,1582年10月4日为星期四,1582年10月15日为星期五,中间的10天被删除。进行推算时将公元1月1日“看成”星期一即可。
我们先来按照此思路验证一下 2020 年 3 月 29 日 是星期几
# include <iostream>
bool run(int num) {
return (num % 4 == 0 && num % 100 != 0) || num % 400 == 0;
}
int main() {
int s2 = 0;
for (int i=1; i<2020; i++) {
if (run(i)) {
s2 += 366;
} else {
s2 += 365;
}
}
s2 += 31 + 29 + 29;
std::cout << s2 % 7;
return 0;
}
输出结果为 0
, 代表星期日。
AC代码
# include <iostream>
bool run(int num) {
return (num % 4 == 0 && num % 100 != 0) || num % 400 == 0;
}
int main() {
int y2 = 2000;
int m2 = 12;
int d2 = 31;
int s2 = 0;
for (int i=1; i<=y2; i++) {
if (run(i)) {
s2 += 366;
} else {
s2 += 365;
}
}
int y1 = 1901;
int m1 = 1;
int d1 = 1;
int s1 = 0;
for (int i=1; i<y1; i++) {
if (run(i)) {
s1 += 366;
} else {
s1 += 365;
}
}
s1 += 1;
int cnt = 0;
for (int i=s1; i<=s2; i++) {
if (i % 7 == 1) {
++cnt;
}
}
std::cout << cnt;
return 0;
}
在数论中,计算日期还有 基姆拉尔森计算公式 和 蔡勒公式 ,在此不做展开。 (其实是懒得学)