回文日期(NOIP2016)

题目:回文日期
这题虽然说不难,但是也不能算水了。
我先讲讲思路。60分的算法很好写,就是判断一下是不是回文串,分离每个数位,判断即可。
但我们的目标是满分,所以我来讲讲满分算法。
首先,给的是区间,那么,难免的,我们需要去枚举,但是怎么枚举?
一天一天的加然后判断?想想都可怕,一定不是这样。那么是怎样的呢?
考虑到,一共八位,回文需要前后四位对称,所以,日期不行,我们对称过去,是什么?年!我们以年为单位枚举,就要少了很多无用的枚举。
所以我们的思路是,枚举两个年限之间的每个年(包括端点),然后对称得到月日,判断是否符合日期规则就行了,同时还要注意,在端点年,要判断日期是否在区间内。
下面看代码:

#include<bits/stdc++.h>
using namespace std;
int aa[8],bb[8],cc[4];
int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    int ans=0;
    int ya=(a-a%10000)/10000;        //1
    int yb=(b-b%10000)/10000;
    for(int i=0;i<8;i++){        //2
        aa[i]=a%10;
        a/=10;
        bb[i]=b%10;
        b/=10;
    }
    int ma=aa[3]*10+aa[2];        //3
    int mb=bb[3]*10+aa[2];
    int da=aa[1]*10+aa[0];
    int db=bb[1]*10+bb[0];  
    for(int i=ya;i<=yb;i++){   //4
        int x=i;
        for(int j=0;j<4;j++){     //5
            cc[j]=x%10;
            x/=10;
        }
        int mon=cc[0]*10+cc[1];     //6
        int day=cc[2]*10+cc[3];
        //特判
        if(i==ya){                        //7
            if(!((mon>ma)||(mon==ma&&day>=da))){
                continue;   
            }
        }else if(i==yb){
            if(!((mon<mb)||(mon==mb&&day<=db))){
                continue;
            }
        }   
        if(mon>=1&&mon<=12){            //8
            if(mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12){
                if(day>=1&&day<=31){
                    ans++;
                } 
            }else if(mon==2){
                if((i%4==0&&i%100!=0)||i%400==0){
                    if(day>=1&&day<=29){
                        ans++;
                    }
                }else{
                    if(day>=1&&day<=28){
                        ans++;
                    }
                }
            }else{
                if(day>=1&&day<=30){
                    ans++;
                }
            }
        }
    }
    printf("%d",ans);
    return 0;
} 

代码中标了8个位置,我们下面讲一下。
1处:计算端点年。用取模实现。
2处:将输入日期数位分离,便于3计算。
3处:计算端点月份和日期,便于7处的特判。
4处:枚举闭区间之间的每个年份。
5处:对于每一个枚举的年份,分离数位,便于计算对称后的月和日。
6处:计算对称后的月和日。
7处:特判,如果是端点值,在此判断是否在区间时间内,如果不是,跳过此次循环,如果是继续向下。
8处:依次判断月和日是否合法,月在1到12之间,还要依据月判断时间,注意闰年,就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值