回文日期(NOIP2016)

来源:互联网 发布:csci 软件 编辑:程序博客网 时间:2024/05/21 08:52

题目:回文日期
这题虽然说不难,但是也不能算水了。
我先讲讲思路。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之间,还要依据月判断时间,注意闰年,就行了。

原创粉丝点击