SzNOI之d100题解题报名,日历问题

SzNOI之d100题解题报名,日历问题

d100: 神仙?妖怪?谢谢!

这题的题目有点古怪。解题过程,且慢慢道来。

搞懂这题,算日历,周几等问题,基本都搞清了。

一、几年有几天

二、到今天有几天

三、打印日历



一、几年有几天

从公元一年,到公元n年,共有几天?

这问题似乎相当简单,因为一年有365嘛。比如公元一年,到公元二年,这样算:

var
  y,day:longint;
begin
  y:=2; // 10
  day:=y*365;
  writeln(day);
end.

算下来,似乎一点错误也木有。

那到公元十年呢?是不是把2改成10就可以了?

不可以,因为闰年有366天。要这样计算:

var
  i,y,day,d:longint;

function leapy(y:longint):boolean;
begin
  if(y mod 400=0) or (y mod 4=0) and (y mod 100<>0) then
    exit(true)
  else exit(false);
end;

begin
  y:=10; //2013
  d:=0;
  for i:=1 to y do
    if(leapy(i)) then inc(d);
  day:=y*365+d;
  writeln(day);
end.

是的,要把闰年多出来的一天,也加进去。

应该是3652天,而不是3650天。

分析一下,很容易明白,因为公元四年,与公元八年,是闰年。

把10,改成2013试试?

这样计算天数,并不是最快的。看程序:

var
  i,y,day,d,e:longint;

function leapy(y:longint):boolean;
begin
  if(y mod 400=0) or (y mod 4=0) and (y mod 100<>0) then
    exit(true)
  else exit(false);
end;

begin
  y:=2013;
  d:=0;
  for i:=1 to y do
    if(leapy(i)) then inc(d);
  day:=y*365+d;
  writeln(d);
  writeln(day);
  e:=(y div 4)-(y div 100)+(y div 400);
  writeln(e);
end.

两种算法,得出的结论是一样的,都是488。

当然是第二种算法快得多,不用循环,直接算出来了。

我们可以粗略理解一下,整除4,闰年多了点。那么减去一些(整除100的结果),那又太少了一些,那么再加上一点。。

好了,以下的算法很快就能计算出,从公元一年到y年,共有几个闰年,共有几天:

var
  y,day,d:longint;
begin
  readln(y); // y:=2013;
  d:=(y div 4)-(y div 100)+(y div 400);
  day:=y*365+d;
  writeln(d);
  writeln(day);
end.


二、到今天有几天

从公元一年的一月一日开始,到今天,共有几天呢?

要分三步走:

公元一年,到去年,共有几天。

今年一月,到这个月的前一个月,共有几天。

这个月的一号,到今天,共有几天。

const
  a:array[0..12] of longint =
  (0,31,28,31,30,31,30,31,31,30,31,30,31);
var
  i,t,y,day,d,m,dd:longint;

function leapy(y:longint):boolean;
begin
  if(y mod 400=0) or (y mod 4=0) and (y mod 100<>0) then
    exit(true)
  else exit(false);
end;  

begin
  y:=2013; //2014年的前一年,是2013年
  m:=11;   //当月是11月
  dd:=1;   //1号
  d:=(y div 4)-(y div 100)+(y div 400);
  day:=y*365+d;
  t:=0;
  for i:=1 to m-1 do inc(t,a[i]); //1月到前一个月的天数
  if( (m>2) and leapy(y) ) then inc(t); //闰年多加一天
  inc(day,t);  //到前个月底有几天
  inc(day,dd); //到今天有几天
  writeln(day);
end.

那今天是周几?

公元一年的元旦的前一天,是周日。这个非常好记,因为传说上帝创世纪之后,是在周日休息的。

到了公元一年的第一天,出来干活了,是周一。

公元一年的元旦的前一天,我们暂时称之为公元前末日。

从公元前末日,到今天,相差几天,我们前面已经计算出来了。

而公元前末日,是周日,那今天是周几,就非常好算了,看程序:

const
  a:array[0..12] of longint =
  (0,31,28,31,30,31,30,31,31,30,31,30,31);
var
  i,t,y,day,d,m,dd:longint;

function leapy(y:longint):boolean;
begin
  if(y mod 400=0) or (y mod 4=0) and (y mod 100<>0) then
    exit(true)
  else exit(false);
end;  

begin
  y:=2013; //去年
  m:=11;
  dd:=1;
  d:=(y div 4)-(y div 100)+(y div 400);
  day:=y*365+d;
  t:=0;
  for i:=1 to m-1 do inc(t,a[i]);
  if( (m>2) and leapy(y+1) ) then inc(t); //闰年多加一天
  inc(day,t); //到前个月底有几天
  inc(day,dd); //到今天有几天
  writeln(day);
  case (day mod 7) of
    0 : writeln(‘Sunday‘); //公元前末日是周日
    1 : writeln(‘Monday‘);
    2 : writeln(‘Tuesday‘);
    3 : writeln(‘Wednesday‘);
    4 : writeln(‘Thursday‘);
    5 : writeln(‘Friday‘);
    6 : writeln(‘Saturday‘);
  end;
end.

是周六,对吧?

那么稍微修改一下程序,对于任意年月日是周几,都可以准确、精确地算出来了:

const
  a:array[0..12] of longint =
  (0,31,28,31,30,31,30,31,31,30,31,30,31);
var
  i,t,y,day,d,m,dd:longint;

function leapy(y:longint):boolean;
begin
  if(y mod 400=0) or (y mod 4=0) and (y mod 100<>0) then
    exit(true)
  else exit(false);
end;  

begin
  readln(y,m,dd);
  y:=y-1; //年份算到去年
  d:=(y div 4)-(y div 100)+(y div 400);
  day:=y*365+d;
  t:=0;
  for i:=1 to m-1 do inc(t,a[i]);
  if( (m>2) and leapy(y+1) ) then inc(t); //今年是y+1
  inc(day,t);
  inc(day,dd);
  case (day mod 7) of
    0 : writeln(‘Sunday‘);
    1 : writeln(‘Monday‘);
    2 : writeln(‘Tuesday‘);
    3 : writeln(‘Wednesday‘);
    4 : writeln(‘Thursday‘);
    5 : writeln(‘Friday‘);
    6 : writeln(‘Saturday‘);
  end;
end.



三、打印日历

有了前面的铺垫,解题报告正式开始。

似乎、好像、仿佛,已经没有什么好说的了,直接看程序:

const
  a:array[0..12] of longint =
  (0,31,28,31,30,31,30,31,31,30,31,30,31);
  w:array[0..6] of string =
  (‘Sun‘,‘Mon‘,‘Tue‘,‘Wed‘,‘Thu‘,‘Fri‘,‘Sat‘);
var
  i,t,y,day,d,m,dd:longint;

function leapy(y:longint):boolean;
begin
  if(y mod 400=0) or (y mod 4=0) and (y mod 100<>0) then
    exit(true)
  else exit(false);
end;  

begin
  readln(y,m);
  y:=y-1; //年份算到去年
  dd:=1;
  d:=(y div 4)-(y div 100)+(y div 400);
  day:=y*365+d;
  t:=0;
  for i:=1 to m-1 do inc(t,a[i]);
  if( (m>2) and leapy(y+1) ) then inc(t); //今年是y+1
  inc(day,t);
  inc(day,dd);
  //
  d:=day mod 7; //得出1号是周几
  for i:=0 to 6 do //输出第一行
    write(w[i]:4);
  writeln;
  t:=0;
  for i:=1 to d do begin //输出第二行前面的的空格。d如是0,不进入循环
    write(‘ ‘:4);
    inc(t);
  end;
  dd:=a[m]; //当月有几天
  if( (m=2) and leapy(y+1)) then inc(dd); //如是闰年2月,要加一天
  for i:=1 to dd do begin
    write(i:4);
    inc(t);
    if(t mod 7=0) then writeln; //t为7的倍数,换行
  end;
  writeln;
end.

嗯,好像不太复杂吧。输入年、月,就能打印出日历,很COOL的样子 ^_^

到此结束,有问题请留言。

TOP

时间: 2024-12-27 23:28:55

SzNOI之d100题解题报名,日历问题的相关文章

08年acm区域赛北京赛区 部分题解题报告

08年区域赛北京赛区 http://poj.org/searchproblem?field=source&key=Beijing+2008 POJ 3921 Destroying the bus stations 题目还是比较难的,当时的榜似乎只有4/25的通过/提交,其实题目数据很水.学长转换模型写了网络流求最小割,可以AC,不过自己造了个数据推翻了正确性.我写了个很挫的bfs套bfs,外层是最小的删除点数,内层是求最短路,数据很水可以AC.但比较蛋疼的在于bfs耗内存,而且队列中的点数是阶乘

poj 1008:Maya Calendar(模拟题,玛雅日历转换)

Maya Calendar Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 64795   Accepted: 19978 Description During his last sabbatical, professor M. A. Ya made a surprising discovery about the old Maya calendar. From an old knotted message, profes

圆锥曲线:椭圆小题解题报告

圆锥曲线:椭圆小题解题报告 注意事项: 由于本人水平有限,部分题目解题方法可能非最优解,如有更好方法欢迎在评论区指正. 部分题目讲解可能过于口语化,导致并不符合官方(人教版教材)的要求,请各位在考试中不要学习,使用正确的,符合要求的用语. 本文中可能存在错别字,望发现者在评论区指正. 本篇博客是为记录本人在完成学校作业的过程中遇到的问题,同时给部分同学作为解题参考用. 本篇博客中绘制图像的工具是geogebra. 1~10题: 1 题目: 已知F~1~,F~2~是椭圆\(x^2/4+y^2/3=

2016.8.27一套简单的题解题报告

一套不错的题,需要相关资料的联系我咯 考试分析: 1.  由于题目的名字加上第一道题没读完时我以为是我最不擅长的treeDP(其实不得不说,树和图上的题我真的是不想写,一般都写不对,上课太不认真,这个弱点要加强训练),我直接跳到了最后一道题,明知考3h还用了30min去分析,不过还是感谢,这30min救了我两道题出来: 这套题的确还是比较简单,后两道题只要认真分析数据都不会有问题,也许是因为暑假切了贪心和递推,我对分析数据比较在行,第三题切完之后还有2h,不过没写高精的我有点慌,打算最后留一点时

超5星难度【微软Core allocation】Coding赛题 - 解题思路&amp;优秀代码分享,邀你来“找茬儿”

6月23日英雄会平台发布了一道难度为超5星的微软比赛题目,截止活动结束共有300多名编程爱好者参与线上答题,而最终通过者仅有7人,通过率仅为2%.为什么成绩如此出人意料?是因为原题的英文描述难以理解?还是题目本身的难度太高让很多人望而生畏知难而退? 为此我们诚邀各路英雄豪杰前来切磋探讨,共同发现: 1. 解题思路:本次大赛一等奖获得者-大连理工大学学生__newSolar,提供两种解题思路: 2. 代码样本:雅虎刷题狂人曹鹏专家的代码将作为样本展示,供学习借鉴: 3."一起来找茬儿":

2017年第六届数学中国数学建模国际赛(小美赛)C题解题思路

这篇文章主要是介绍下C题的解题思路,首先我们对这道C题进行一个整体的概括,结构如下: C题:经济类 第一问:发现危险人群. 发现:欺诈的方式开始.雇佣或浪漫的承诺. 数据→确定特定的经济萧条地区→确定最危险的人群→针对这些人群的预防活动 被贩卖的因素(卷入人口贩运的风险因素): 贫困.失业.移民.逃避政治冲突.战争. 第二问:受害者身份和位置 发现:人口贩运网:动态的 贩毒者:频繁地改变分布.运输路线 (以避免被发现) ↓(信息不完整) 执法人员和分析人员→试图识别.摧毁 人口贩卖网络→(信息不

微信小程序:数独挑战之九宫格-中级-第一题解题思路

题目 中级第一题相对比较简单,只要运行唯一余数.排除法基本就能解出来,下面看一下解题路径: 最终答案为: 原文地址:https://www.cnblogs.com/webjlwang/p/10612671.html

CTF的简单题解题 1

这是去IDF实验室做的CTF题:http://ctf.idf.cn/index.php 一.被改错的密码 一看,被修改的密码有33位.只有l不是16进制的,所以把l去掉,然后用md5在线解密就可以解除密码是idf 二.啥? 有种技术叫数据隐写,比方将数据藏在图片的编码里... 用16进制查看器就好了,把图片拉进去...从ASCII码中找到答案了..就在最后 用的HxD 也可以直接右键用记事本打开图片,在最后也会看到答案 三.红与黑 这个只需要改一下图片的亮度和色调就能看出图片底下黑色部分显示的答

算多题解题思路

根据自己刷过的算法题,一般通过如下思路解决: 1,最常见的就是字符串处理: 2,常见的排序算法: 3,二分查找: 4,双指针: 5,位处理: 6,回溯算法: 7,动态规划: 8,不仅仅要考虑代码的功能性(对正确的输入能有真确的输出),还要考虑代码的鲁棒性(能够处理错误的输入,而不会导致程序的崩溃) 鲁棒性:如对于链表,输入空链表,输入链表只有一个节点等等: 9,能用递归的基本都能用迭代: