日期问题整理

  1. 判断闰年

判断闰年闰年的判别法:
参考解法一
如果a%4!=0,则a不是闰年;
否则a%100==0&&a%400!=0,则a不是闰年;
则a是闰年。
参考解法二:列出所有闰年的可能条件;如果

 year%4==0&&year%100!=0||year%400==0

则a是闰年,否则不是。
参考程序一

#include<stdio.h>
int main()
{
	int year,leap;
	printf("enter year ");//交互语
	scanf("%d",&year);//输入年份
	if(year%4==0)
	{
		if(year%100==0)
		{
			if(year%400==0)
			  leap=1;
			else
			  leap=0;
		}
		else
		  leap=1;
	}
	else
	leap=0;
	if(leap)
	  printf("%d is ",year);
    else
      printf("%d is not ",year);
    printf("a leap year.\n"); 
	return 0;
 } 

参考程序二:

#include<stdio.h>
int main()
{
 int year,leap;
 printf("enter year:");
 scanf("%d",&year);
 if(year%4!=0)
   leap=0;
 else if(year%100==0)
   leap=1;
 else if(year%400==0)
   leap=1;
    else
    leap=0;
 if(leap)
      printf("%d is ",year);
    else
    printf("%d is not ",year);
    printf("a leap year.");
 return 0;
 } 

参考程序三:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int year,leap;
	printf("enter year:");
	scanf("%d",&year);
	if(year<=0)
	{
		printf("输入数据错误!\n");
		exit(0);
	}
	if(year%4==0&&year%100!=0||year%400==0)
	  leap=1;
	else
	  leap=0;
	if(leap)
	  printf("%d is ",year);
	else
	  printf("%d is not ",year);
	printf("a leap year.");
	return 0;
 } 

分析:
判断一个数能否被另一个整数整除应该用整数取模运算,而不是用整数除法运算。避免逻辑错误,代码冗长等问题。

  1. 细菌繁殖
/*题目描述:
一种细菌的繁殖速度是每天成倍增长。例如:第一天有10个,第二天就变成20个,第三天变成40个,
第四天变成80个,……。现在给出第一天的日期和细菌数目,要你写程序求出到某一天的时候,细菌的数目。
输入描述:
第一行有一个整数n,表示测试数据的数目。其后n行每行有5个整数,整数之间用一个空格隔开。
第一个数表示第一天的月份,第二个数表示第一天的日期,第三个数表示第一天细菌的数目,
第四个数表示要求的那一天的月份,第五个数表示要求的那一天的日期。已知第一天和要求的一天
在同一年并且该年不是闰年,要求的一天一定在第一天之后。数据保证要求的一天的细菌数目在长整数(long)范围内。
输出描述:
对于每一组测试数据,输出一行,该行包含一个整数,为要求的一天的细菌数。
样例输入:
2
1 1 1 1 2
2 28 10 3 2
样例输出:
2
40*/

解题思路
实际上就是求给定的两天之间的间隔天数n,第一天的细菌数乘以2的n次方就是答案。每个月的天数因为很不固定,可以使用一个数组将每个月的天数存起来。

  • 读入测试样例数n;
  • 读入两个日期及第一天的细菌数;
  • 将两个日期转换为当年的第几天;
  • 得到两个天数的差,即间隔天数m;
  • 用第一天的细菌数乘以2的m次方得到x;
  • 输出x;
#include<iostream>
using namespace std;
int main()
{
	int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
//该年不是闰年;
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)//多组输入;
	{
		int month1, date1, month2, date2, num;
//输入日期;
		cin >> month1 >> date1 >> num >> month2 >> date2;
		int sum = 0;//每次循环将sum重置为0;
		for (int k = month1; k < month2; k++)
		{
			sum += days[k - 1];
		}
		sum -= date1;
		sum += date2;


		long nums = num;//注意,此处将循环判断条件与运算分开,避免影响。
		for (int k = 0; k < sum; k++)
		{
			nums *= 2;
		}
		cout << nums << endl;
	}
	return 0;
}

3.日历问题1.0

/*题目:输入某年某月某日,判断这一天是这一年的第几天?*/

参考程序一

#include<stdio.h>
int leap(int x)//判断闰年的函数
{
	if((x%4==0&&x%100!=0)||x%400==0)
	return 1;
	else
	return 0;
}
int main()
{
	int year,month,day;
	int sum=0;
	int i;
	int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};//闰年各月天数
	int b[12]={31,29,31,30,31,30,31,31,30,31,30,31};//平年各月天数
	printf("请输入日期:(例:2019 2 16)\n");
	scanf("%d %d %d",&year,&month,&day);
	if(leap(year))
	{
		for(i=0;i<month-1;i++)
		sum+=b[i];
	 } 
	 else
	 for(i=0;i<month-1;i++)
	 sum+=a[i];
	 printf("sum=%d\n",sum+day);
	return 0;
}

//注意循环的边界
参考程序二

//添加判断二月日期是否正确 
#include <stdio.h>
void main()
{
int year,month,day,sum,m;
printf("请输入年月日(如:1991,1,1)\n");
scanf("%d,%d,%d",&year,&month,&day);
if((month==2&&day==30)||(month==2&&day==31))
{
printf("2月没有%d天,请重新输入:",day);
scanf("%d,%d,%d",&year,&month,&day); 
}
if((year%4==0&&year%100!=0)||(year%400==0))
{
m=29;	
} 
else
{
m=28;
} 
switch(month)
{
case 1: sum=0;
break;
case 2: sum=31;
break;
case 3: sum=m+31;
break;
case 4: sum=m+31+31;
break;
case 5: sum=m+31+31+30;
break;
case 6: sum=m+31+31+30+31;
break;
case 7: sum=m+31+31+30+31+30;
break;
case 8: sum=m+31+31+30+31+30+31;
break;
case 9: sum=m+31+31+30+31+30+31+31;
break;
case 10: sum=m+31+31+30+31+30+31+31+30;
break;
case 11: sum=m+31+31+30+31+30+31+31+30+31;
break;
case 12: sum=m+31+31+30+31+30+31+31+30+31+30;
break; 
}
sum=sum+day;
printf("%d,%d,%d是这年当中的第%d天\n",year,month,day,sum);
}

参考程序三

#include<stdio.h>
int main()
{
int day,month,year,sum,leap;
printf("\n请输入年,月,日,格式为:年,月,日(2015,12,10)\n");
scanf("%d,%d,%d",&year,&month,&day);
switch(month)
{
case 1:sum=0;break;
case 2:sum=31;break;
case 3:sum=59;break;
case 4:sum=90;break;
case 5:sum=120;break;
case 6:sum=151;break;
case 7:sum=181;break;
case 8:sum=212;break;
case 9:sum=243;break;
case 10:sum=273;break;
case 11:sum=304;break;
case 12:sum=334;break;
default:printf("dtat error");break;
}
sum=sum+day;//加上天数
if(year%400==0||(year%4==0&&year%100!=0)) {
leap=1;
}  else {
leap=0;
}
if(leap==1&&month>2) {
sum++;
}
printf("这是这一年的第%d天。",sum);
printf("\n");
}

4.日历问题2.0

/*题目描述:
已知 2007 年 10 月 10 日,请求出 n 天后是几月几号
输入描述:
多组输入,每组输入为 1 行,为一个正整数 n (1 <= n <= 2000)
输出描述:
对于每组输入,输出格式为 yyyy-mm-dd,输出的值为 n 天后的日期
样例输入:
1
2
样例输出:
2007-10-11
2007-10-12*/

参考程序

#include<stdio.h>
int leap(int year1)
{
	if (year1 % 4 != 0 || (year1 % 100 == 0 && year1 % 400 != 0))
		return 0;
	else
		return 1;
}
int main()
{
	int n;    //第n天
	int i, j, k;
	//定义二维数组存储闰年及非闰年的月数
	int months[2][12] = { 31,28,31,30,31,30,31,31,30,31,30,31,31,29,31,30,31,30,31,31,30,31,30,31 };
	int years[2] = { 365,366 };    //存储闰年及非闰年的总天数
	while (scanf("%d", &n) != EOF)
	{
		n += 282;
		for (i = 2007; n >= years[leap(i)]; i++)
			n -= years[leap(i)];
		for (j = 0; n >= months[leap(i)][j]; j++)
			n = n - months[leap(i)][j];
		printf("%d-%02d-%02d\n", i, j + 1, n + 1);




	}
	return 0;

5.日历问题3.0

//给定公元2000年1月1日开始逝去的天数,你的任务是给出这一天是哪年,那月,那日,星期几
//输入数据,输入包含若干行,每行包含一个整数,表示从2000年1月1日开始逝去的天数。输入最后一行是-1,不必处理。可以假设结果不会超过9999;
//输出描述:对每个测试样例输出一行,该行包括对应的日期和星期几。格式为“YYYY-MM-DD DayOfWeek”;

参考程序

#include<iostream>
using namespace std;
int leap(int x)//判断闰年的函数,是则返回1,不是则返回0 
{
	if((x%4==0&&x%100!=0)||x%400==0)
	return 1;
	else
	return 0;
}
int main()
{
	char week[7][12]={"Saturday","Sunday","Monday","Quesday","Wednesday","Thuisday","Friday"};
	int year[2]={365,366};//year[0]表示非闰年的天数,year[1]表示闰年的天数; 
	int months[2][12] = { 31,28,31,30,31,30,31,31,30,31,30,31,31,29,31,30,31,30,31,31,30,31,30,31 };
	//months[0]表示非闰年里每个月的天数,months[1]表示闰年里每个月的天数;
	int days,dayofweek;//days表示输入的天数,dayofweek表示星期几
	int i=0,j=0;
	while(scanf("%d",&days)&&days!=-1)
	{
		dayofweek=days%7;
		for(i=2000;days>=year[leap(i)];i++)
		days-=year[leap(i)];
		for(j=0;days>=months[leap(i)][j];j++)
		days-=months[leap(i)][j];
		printf("%d-%02d-%02d %s\n",i,j+1,days+1,week[dayofweek]);
	 } 
	return 0;
 } 

6**.玛雅日历**

/*题目描述:
上周末,M.A. Ya教授对古老的玛雅有了一个重大发现。从一个古老的节绳(玛雅人用于记事的工具)中,
教授发现玛雅人使用了一个一年有365天的叫做Haab的历法。这个Haab历法拥有19个月,在开始的18个月,
一个月有20天,月份的名字分别是pop, no, zip, zotz, tzec, xul, yoxkin, mol, chen, yax, zac, 
ceh, mac, kankin, muan, pax, koyab, cumhu。这些月份中的日期用0到19表示。Haab历的最后一个月叫做uayet,
它只有5天,用0到4表示。玛雅人认为这个日期最少的月份是不吉利的,在这个月法庭不开庭,人们不从事交易,甚至没有人打扫屋中的地板。
因为宗教的原因,玛雅人还使用了另一个历法,在这个历法中年被称为Tzolkin(holly年),一年被分成13个不同的时期,
每个时期有20天,每一天用一个数字和一个单词相组合的形式来表示。使用的数字是1-13,使用的单词共有20个,
它们分别是:imix, ik, akbal, kan, chicchan, cimi, manik, lamat, muluk, ok, chuen, eb, ben, ix, 
mem, cib, caban, eznab, canac, ahau。
注意:年中的每一天都有着明确唯一的描述,比如,在一年的开始,日期如下描述: 
1 imix, 2 ik, 3 akbal, 4 kan, 5 chicchan, 6 cimi, 7 manik, 8 lamat, 9 muluk, 10 ok, 11 chuen, 12 eb, 
13 ben, 1 ix, 2 mem, 3 cib, 4 caban, 5 eznab, 6 canac, 7 ahau, ,8 imix, 9 ik, 10 akbal ……
也就是说数字和单词各自独立循环使用。
Haab历和Tzolkin历中的年都用数字0,1,……表示,数字0表示世界的开始。所以第一天被表示成:
Haab: 0 pop 0
Tzolkin: 1 imix 0
请帮助M.A. Ya教授写一个程序可以把Haab历转化成Tzolkin历。
输入描述:
第一行表示要转化的Haab 历的数据量。下面的每一行表示一个日期。
Haab历中的数据由如下的方式表示:日期 月份 年数。其中年数小于5000。
输出描述:
每行表示一个对应的Tzolkin 历日期。Tzolkin 历中的数据由如下的方式表示: 天数字 天名称 年数。
样例输入:
3
10 zac 0
0 pop 0
10 zac 1995
样例输出:
3 chuen 0
1 imix 0
9 cimi 2801*/

参考程序

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	int n;
	cin >> n;
	//	while(n--)
	for (int i = 0; i < n; i++)
	{
		//const int LEN 10;
		char month1[19][10] = { "pop", "no", "zip", "zotz", "tzec", "xul", "yoxkin", "mol", "chen", "yax", "zac", "ceh", "mac", "kankin", "muan", "pax", "koyab", "cumhu" };
		char month2[20][10] = { "imix", "ik", "akbal", "kan", "chicchan", "cimi"," manik", "lamat", "muluk", "ok", "chuen", "eb", "ben", "ix", "mem", "cib", "caban", "eznab", "canac", "ahau" };
		int year, day, dates;
		char month[10];
		int m;
		cin >> day >> month >> year;  //读出haab的日月年 
		for (m = 0; m < 19; m++)  //找到月份对应的数字m 
		{
			if (!strcmp(month1[m], month))
				break;
		}
		//计算距离世界开始的天数,从0开始
		dates = m * 20 + year * 365 + day;
		//输出tzolkin的日期
		cout << 1 + dates % 13 << " " << month2[dates % 20] << " " << dates / 260 << endl;
	}
	return 0;
}

7.时区转换

/*题目描述:
直到 19 世纪,时间校准是一个纯粹的地方现象。每一个村庄当太阳升到最高点的时候把他们的时钟调到中午 12 点。
一个钟表制造商人家或者村里主表的时间被认为是官方时间,市民们把自家的钟表和这个时间对齐。每周一些热心的市民会带着时间标准的表,
游走大街小巷为其他市民对表。在城市之间旅游的话,在到达新地方的时候需要把怀表校准。但是,当铁路投入使用之后,
越来越多的人频繁地长距离地往来,时间变得越来越重要。在铁路的早期,时刻表非常让人迷惑,
每一个所谓的停靠时间都是基于停靠地点的当地时间。时间的标准化对于铁路的高效运营变得非常重要。




在 1878 年,加拿大人 Sir Sanford Fleming 提议使用一个全球的时区(这个建议被采纳,并衍生了今天我们所使用的全球时区的概念)。
他建议把世界分成 24 个时区,每一个跨越 15 度经线(因为地球的经度 360 度,划分成 24 块后,一块为 15 度)。
Sir Sanford Fleming 的方法解决了一个全球性的时间混乱的问题。美国铁路公司于 1883 年 11 月 18 日使用了 Fleming 提议的时间方式。
1884 年一个国际子午线会议在华盛顿召开,会议的目的是选择一个合适的本初子午线。大会最终选定了格林尼治为标准的 0 度。
尽管时区被确定了下来,但是各个国家并没有立刻更改他们的时间规范。在美国,尽管到 1895 年已经有很多州开始使用标准时区时间,
而国会直到 1918 年才强制使用会议制定的时间规范。今天,各个国家使用的是一个 Fleming 时区规范的一个变种。中国一共跨越了 5 个时区,
但是使用了一个统一的时间规范,比 Coordinated Universal Time(UTC,格林尼治时间)早 8 个小时;俄罗斯也拥护这个时区规范,
尽管整个国家使用的时间和标准时区提前了 1 个小时;澳大利亚使用 3 个时区,其中主时区提前于 Fleming 规范的时区半小时。
很多中东国家也使用了半时时区(即不是按照 Fleming 的 24 个整数时区)。因为时区是对经度进行划分,
在南极或者北极工作的科学家直接使用了 UTC 时间,否则南极大陆将被分解成 24 个时区。




时区间的转化表如下:




UTC (Coordinated Universal Time), 定义为 UTC
GMT(Greenwich Mean Time), 定义为 UTC
BST (British Summer Time), 定义为 UTC+1 hour
IST (Irish Summer Time), 定义为 UTC+1 hour
WET (Western Europe Time), 定义为 UTC
WEST (Western Europe Summer Time), 定义为 UTC+1 hour
CET (Central Europe Time), 定义为 UTC+1 hour
CEST (Central Europe Summer Time), 定义为 UTC+2 h
EET (Eastern Europe Time), 定义为 UTC+2 h
EEST (Eastern Europe Summer Time), 定义为 UTC+3 h
MSK (Moscow Time), 定义为 UTC+3 h
MSD (Moscow Summer Time), 定义为 UTC+4 h
AST (Atlantic Standard Time), 定义为 UTC-4 h
ADT (Atlantic Daylight Time), 定义为 UTC-3 h
NST (Newfoundland Standard Time), 定义为 UTC-3.5 h
NDT (Newfoundland Daylight Time), 定义为 UTC-2.5 h
EST (Eastern Standard Time), 定义为 UTC-5 h
EDT (Eastern Daylight Saving Time), 定义为 UTC-4 h
CST (Central Standard Time), 定义为 UTC-6 h
CDT (Central Daylight Saving Time), 定义为 UTC-5 h
MST (Mountain Standard Time), 定义为 UTC-7 h
MDT (Mountain Daylight Saving Time), 定义为 UTC-6 h
PST (Pacific Standard Time), 定义为 UTC-8 h
PDT (Pacific Daylight Saving Time), 定义为 UTC-7 h
HST (Hawaiian Standard Time), 定义为 UTC-10 h
AKST (Alaska Standard Time), 定义为 UTC-9 h
AKDT (Alaska Standard Daylight Saving Time), 定义为 UTC-8 h
AEST (Australian Eastern Standard Time), 定义为 UTC+10 h
AEDT (Australian Eastern Daylight Time), 定义为 UTC+11 h
ACST (Australian Central Standard Time), 定义为 UTC+9.5 h
ACDT (Australian Central Daylight Time), 定义为 UTC+10.5 h
AWST (Australian Western Standard Time), 定义为 UTC+8 h
下面给出了一些时间,请在不同时区之间进行转化。
输入描述:
输入的第一行包含了一个整数 N,表示有 N 组测试数据。
接下来 N 行,每一行包括一个时间和两个时区的缩写,它们之间用空格隔开。
时间由标准的 a.m./p.m 给出。midnight 表示晚上 12 点(12:00 a.m.),noon 表示中午 12 点(12:00 p.m.)。
输出描述:
假设输入行给出的时间是在第一个时区中的标准时间,要求输出这个时间在第二个时区中的标准时间。
样例输入:
4
noon HST CEST
11:29 a.m. EST GMT
6:01 p.m. CST UTC
12:40 p.m. ADT MSK
样例输出:
midnight
4:29 p.m.
12:1 a.m.
6:40 

参考程序:

#include<iostream>
#include<cstring>
using namespace std;
int dif(char *a1, char *a2)
{
	char a[32][10] = { "UTC","GMT","BST","IST","WET","WEST","CET","CEST","EET","EEST","MSK","MSD","AST","ADT","NST","NDT","EST","EDT","CST","CDT","MST","MDT","PST","PDT","HST","AKST","AKDT","AEST","AEDT","ACST","ACDT","AWST" };
	float time[32] = { 0,0,1,1,0,1,1,2,2,3,3,4,-4,-3,-3.5,-2.5,-5,-4,-6,-5,-7,-6,-8,-7,-10,-9,-8,10,11,9.5,10.5,8 };
	int i, j;
	for (i = 0; strcmp(a[i], a1); i++);
	for (j = 0; strcmp(a[j], a2); j++);
	return (int)((time[i] - time[j]) * 60);
}
int main()
{
	int n, i;
	cin >> n;
	for (i = 0; i < n; i++)
	{
		int h, m;
		char t[9];
		cin >> t;
		switch (t[0])
		{
		case 'n':h = 12;
			m = 0;
			break;
		case 'm':h = 0;
			m = 0;
			break;
		default:sscanf(t, "%d:%d", &h, &m);
			h %=12;
			cin >> t;
			if (t[0] == 'p') 
				h += 12;
		}
		char timea1[5], timea2[5];
		cin >> timea1 >> timea2;
		int newtime;
		newtime = h * 60 + m + dif(timea2, timea1);
		if (newtime < 0) newtime += 1440;
		newtime %= 1440;
		switch (newtime)
		{
		case 0:
			cout << "midnight" << endl;
			break;
		case 720:
			cout << "noon" << endl;
			break;
		default:
			h = newtime / 60;
			m = newtime % 60;
			if (h == 0)
			    cout << "12:" << m << " a.m." << endl;
			else if (h < 12)
			    cout << h << ':' << " a.m." << endl;
			else if (h == 12)
			    cout << "12:" << m << " p.m." << endl;
			else
			    cout << h % 12 << ':' << m << " p.m." << endl;
		}
	}
	return 0;
}

8.不吉利的日期

在国外,每月的 13 号和每周的星期 5 都是不吉利的。特别是当 13 号那天恰好是星期 5时,更不吉利。
已知某年的一月一日是星期w,并且这一年不是闰年,求出这一年所有13号那天是星期五的月份,按从小到大的顺序输出数字(W=1~7)

参考程序

#include<stdio.h>
int main()
{
	int months[13]={0,12,31,28,31,30,31,30,31,31,30,31,30};
	int w,i;
	scanf("%d",&w);
	for(i=1;i<=12;i++)
	{
		w=(w+months[i])%7;
		if(w==5)
		printf("%d\n",i);
	}
	return 0;
 } 
发布了4 篇原创文章 · 获赞 4 · 访问量 133

猜你喜欢

转载自blog.csdn.net/qq_43629083/article/details/90297724