日期处理与进制转换

这篇文章将介绍常见的日期处理与进制转换问题。

1.日期处理

以题目为例:http://codeup.hustoj.com/problem.php?cid=100000578&pid=0

问题 A: 日期差值

题目描述

有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。

输入

有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD

输出

每组数据输出一行,即日期差值

样例输入

20130101
20130105

样例输出

5

细节

我们需要处理平年和闰年,大月和小月的问题。

思路

我们不妨设第一个日期是早于第二个日期的(如果不是就交换顺序)。

求日期差值的问题很直接的一个思路就是让第一个日期不断加1天,直到和第二个日期相等为止。

为了存放平年和闰年每个月的天数,我们建立一个二维数组int month[13][2],第一维存放月份,从1到12,第0位不用,第二维为0表示平年,为1表示闰年。

我们可以先让第一个日期的年份加到与第二个日期的年份相差1为止,这样可以加快速度。对于其中的年份,只要根据平年还是闰年加365或366天即可。之后再不断让天数加1就行。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
 
bool isLeap(int y){
    return (y%4==0 &&y%100!=0) || (y%400==0);
}
int month[13][2] = {
	{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},
	{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}
};
int main()
{     
    int time1,time2;
    int y1,m1,d1;
    int y2,m2,d2;     
    while(scanf("%d%d",&time1,&time2) != EOF){// 有多组测试数据
		int ans = 1;
		if (time1 > time2) swap(time1,time2);
    	if(time1 == time2) {printf("%d\n",1);continue;}
     
    	y1 = time1/10000,m1 = time1%10000/100,d1 = time1%100;
    	y2 = time2/10000,m2 = time2%10000/100,d2 = time2%100;
		////if (isLeap(y1)  && m1 <= 2) ans += 1;
		while (y1 < y2 || m1 < m2 || d1 < d2){			
			if (y1 < y2 -1){ // 优化判断
				y1 ++;
				if (isLeap(y1)) ans+=366;
				else ans += 365;
				continue;
			}
			d1++; // 注意这里放优化判断之后
			if (d1==month[m1][isLeap(y1)]+1){
				d1 = 1;m1++;
			}
			if (m1 == 13){
				m1 = 1;y1++;
			}
			ans++;
		}
		printf("%d\n",ans);
	}
    return 0;
}

优化代码参考:https://blog.csdn.net/numb123r/article/details/112722689

优化代码经过测试,存在漏洞,“20200229;20220301”这组数据会少一天,好像从闰年开始日期<=2月都会少一天。

CODEUP的数据应该不完整,上面这组数据和优化前代码答案不一样,但都能过。

把25行代码解注释应该就是正确答案,但是AC不了。

直接硬算是最靠谱的,不需要对年数优化。

2.进制转换

以题目为例:

https://pintia.cn/problem-sets/994805260223102976/problems/994805299301433344

1022 D进制的A+B (20 分)

输入两个非负 10 进制整数 AB (≤230−1),输出 A+BD (1<D≤10)进制数。

输入格式:

输入在一行中依次给出 3 个整数 ABD

输出格式:

输出 A+BD 进制数。

输入样例:

123 456 8

输出样例:

1103

思路

将一个P进制数转换为Q进制数,分两步:

  1. 将P进制数x转换为10进制数y:
int y = 0,product = 1;
while (x!=0){
    y += (x%10)*product; // x%10取最后一位数
    x /= 10; // 舍去x的最后一位数
    product *= P; // product作为权
}

搞不清楚的话,可以拿二进制数转换为十进制数作为参考。
2. 将10进制数y转换为Q进制数z:

除基取余法。

int z[40],num = 0; // 数组z用于存放Q进制数y的每一位,num为位数
do{
    z[num++]  = y % Q;
    y /= Q;
}while (y != 0);

最后将数组z从高位z[num-1]到低位z[0]输出,就是Q进制数z。

搞不清楚的话,可以拿十进制数转换为二进制数作为参考。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
    int a,b,d;
    scanf("%d%d%d",&a,&b,&d);
    a  = a+b;
    int ans[31],num = 0;
    do{
        ans[num++] = a%d;
        a /= d;
    }while (a != 0);
    for (int i=num-1;i>=0;i--){
        printf("%d",ans[i]);
    }
    puts("");
    return 0;
}

提一点,PAT的编译器,如果按照scanf的一般写法可能会警告,将scanf("%d",&t);改成if(scanf("%d",&t)){};就不会警告了。

posted @ 2021-07-12 12:42  grant_drew  阅读(214)  评论(0)    收藏  举报