日期处理与进制转换
这篇文章将介绍常见的日期处理与进制转换问题。
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 进制整数 A 和 B (≤230−1),输出 A+B 的 D (1<D≤10)进制数。
输入格式:
输入在一行中依次给出 3 个整数 A、B 和 D。
输出格式:
输出 A+B 的 D 进制数。
输入样例:
123 456 8
输出样例:
1103
思路
将一个P进制数转换为Q进制数,分两步:
- 将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)){};就不会警告了。

浙公网安备 33010602011771号