zoukankan      html  css  js  c++  java
  • ZOJ 3950

    从Y1-M1-D1到Y2-M2-D2间所有日期,出现多少个9?

    呃讲真,刚开始想这个题目还是很烦的,各种要考虑的情况……

    最后思考这样:

    对于任何输入,设输入分别为 st.y  st.m  st.d  ed.y  ed.m  ed.d ,分成三种情况:

    ①st.y==ed.y,两个日期出现在同一年里,直接暴力查[st,ed]间出现多少个9;

    ②ed.y-st.y==1,两个日期出现在相邻年,直接查[st,st这一年的12.31]+[ed这一年的1.1,ed];

    ③ed.y-st.y>1,这样,除了②要查的,还要在加上中间那些一整年一整年出现了多少个9;

    这样,我们就需要一个函数calc(year,month1,day1,month2,day2)来计算同一年内从某天到某天,这么多天里出现了多少个9

    另外,我们还需要计算出中间那些整年整年的,出现了多少个9;

    然后就有了如下超时代码:

      1 #include<cstdio>
      2 struct Date{
      3     int y,m,d;
      4 }st,ed,mid;
      5 int cnt;
      6 int leap_md[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
      7 int not_leap_md[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
      8 bool is_leap_year(int year)
      9 {
     10     if(year%100==0)
     11     {
     12         if(year%400==0) return true;
     13         else return false;
     14     }
     15     else
     16     {
     17         if(year%4==0) return true;
     18         else return false;
     19     }
     20 }
     21 int calc(int year,int m1,int d1,int m2,int d2)
     22 {
     23     int cnt=0;
     24     
     25     for(int month=m1;month<=m2;month++)
     26     {
     27         
     28         if(month==m1)
     29         {
     30             int max_day=is_leap_year(year)?(leap_md[month]):(not_leap_md[month]);
     31             for(int day=d1;day<=max_day;day++)
     32             {
     33                 if(day%10 == 9) cnt++;
     34                 if(day/10 == 9) cnt++;
     35                 
     36                 if(year%10 == 9) cnt++;
     37                 if(year/10%10 == 9) cnt++;
     38                 if(year/100%10 == 9) cnt++;
     39                 if(year/1000 == 9) cnt++;
     40                 
     41                 if(month%10 == 9) cnt++;
     42                 if(month/10 == 9) cnt++;
     43             }
     44         }
     45         else if(month==m2)
     46         {
     47             for(int day=1;day<=d2;day++)
     48             {
     49                 if(day%10 == 9) cnt++;
     50                 if(day/10 == 9) cnt++;
     51                 
     52                 if(year%10 == 9) cnt++;
     53                 if(year/10%10 == 9) cnt++;
     54                 if(year/100%10 == 9) cnt++;
     55                 if(year/1000 == 9) cnt++;
     56                 
     57                 if(month%10 == 9) cnt++;
     58                 if(month/10 == 9) cnt++;
     59             }
     60         }
     61         else
     62         {
     63             int max_day=is_leap_year(year)?(leap_md[month]):(not_leap_md[month]);
     64             for(int day=1;day<=max_day;day++)
     65             {
     66                 if(day%10 == 9) cnt++;
     67                 if(day/10 == 9) cnt++;
     68                 
     69                 if(year%10 == 9) cnt++;
     70                 if(year/10%10 == 9) cnt++;
     71                 if(year/100%10 == 9) cnt++;
     72                 if(year/1000 == 9) cnt++;
     73                 
     74                 if(month%10 == 9) cnt++;
     75                 if(month/10 == 9) cnt++;
     76             }
     77         }
     78     }
     79     return cnt;
     80 }
     81 int main()
     82 {
     83     int t;
     84     scanf("%d",&t);
     85     while(t--)
     86     {
     87         scanf("%d%d%d%d%d%d",&st.y,&st.m,&st.d,&ed.y,&ed.m,&ed.d);
     88         if(st.y==ed.y)
     89         {
     90             printf("%d
    ",calc(st.y ,st.m, st.d, ed.m, ed.d));
     91             continue;
     92         }
     93         else if(ed.y-st.y==1)
     94         {
     95             printf("%d
    ",calc(st.y ,st.m, st.d, 12, 31)+calc(ed.y , 1, 1, ed.m, ed.d));
     96             continue;
     97         }
     98         else
     99         {
    100             int ans=0;
    101             for(int year=st.y+1; year<=ed.y-1; year++)
    102             {
    103                 if(is_leap_year(year)) ans+=66;
    104                 else ans+=65;
    105                 
    106                 int cnt=0;
    107                 if(year%10 == 9) cnt++;
    108                 if(year/10%10 == 9) cnt++;
    109                 if(year/100%10 == 9) cnt++;
    110                 if(year/1000 == 9) cnt++;
    111                 cnt*=is_leap_year(year)?(366):(365);
    112                 
    113                 ans+=cnt;
    114             }
    115             ans+=calc(st.y ,st.m, st.d, 12, 31)+calc(ed.y , 1, 1, ed.m, ed.d);
    116             printf("%d
    ",ans);
    117             continue;
    118         }
    119     }
    120 }

    其中需要注意的是,一整年中:不看年,单纯月和日,9会出现66或65次(闰年/非闰年);加上年的,年份里9的个数*365或者366。

    但是很不幸的就TLE了,定睛一看,测试数据高达1e5,我们算整年的循环,大概每个test最坏情况循环8000次不到一些,再乘上1e5,就会超过1s,就会T,所以我们要预处理整年整年的

      1 #include<cstdio>
      2 #include<cstring>
      3 struct Date{
      4     int y,m,d;
      5 }st,ed,mid;
      6 int cnt;
      7 int leap_md[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};//闰年的每一个月有多少天 
      8 int not_leap_md[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//非闰年的每一个月有多少天
      9 int num[10000];
     10 bool is_leap_year(int year) 
     11 {
     12     if(year%100==0)
     13     {
     14         if(year%400==0) return true;
     15         else return false;
     16     }
     17     else
     18     {
     19         if(year%4==0) return true;
     20         else return false;
     21     }
     22 }
     23 int calc(int year,int m1,int d1,int m2,int d2)
     24 {
     25     int cnt=0;
     26     if(m1==m2)//前后日期在同一个月 
     27     {
     28         for(int day=d1;day<=d2;day++)
     29         {
     30             if(day%10 == 9) cnt++;
     31             if(day/10 == 9) cnt++;
     32                 
     33             if(year%10 == 9) cnt++;
     34             if(year/10%10 == 9) cnt++;
     35             if(year/100%10 == 9) cnt++;
     36             if(year/1000 == 9) cnt++;
     37                 
     38             if(m1%10 == 9) cnt++;
     39             if(m1/10 == 9) cnt++;
     40         }
     41         return cnt;
     42     }
     43     
     44     for(int month=m1;month<=m2;month++)//按月循环 
     45     {
     46         
     47         if(month==m1)//特判开始日期所在月 
     48         {
     49             int max_day=is_leap_year(year)?(leap_md[month]):(not_leap_md[month]);
     50             for(int day=d1;day<=max_day;day++)
     51             {
     52                 if(day%10 == 9) cnt++;
     53                 if(day/10 == 9) cnt++;
     54                 
     55                 if(year%10 == 9) cnt++;
     56                 if(year/10%10 == 9) cnt++;
     57                 if(year/100%10 == 9) cnt++;
     58                 if(year/1000 == 9) cnt++;
     59                 
     60                 if(month%10 == 9) cnt++;
     61                 if(month/10 == 9) cnt++;
     62             }
     63         }
     64         else if(month==m2)//特判结束日期所在月 
     65         {
     66             for(int day=1;day<=d2;day++)
     67             {
     68                 if(day%10 == 9) cnt++;
     69                 if(day/10 == 9) cnt++;
     70                 
     71                 if(year%10 == 9) cnt++;
     72                 if(year/10%10 == 9) cnt++;
     73                 if(year/100%10 == 9) cnt++;
     74                 if(year/1000 == 9) cnt++;
     75                 
     76                 if(month%10 == 9) cnt++;
     77                 if(month/10 == 9) cnt++;
     78             }
     79         }
     80         else//其他月份 
     81         {
     82             int max_day=is_leap_year(year)?(leap_md[month]):(not_leap_md[month]);
     83             for(int day=1;day<=max_day;day++)
     84             {
     85                 if(day%10 == 9) cnt++;
     86                 if(day/10 == 9) cnt++;
     87                 
     88                 if(year%10 == 9) cnt++;
     89                 if(year/10%10 == 9) cnt++;
     90                 if(year/100%10 == 9) cnt++;
     91                 if(year/1000 == 9) cnt++;
     92                 
     93                 if(month%10 == 9) cnt++;
     94                 if(month/10 == 9) cnt++;
     95             }
     96         }
     97     }
     98     return cnt;
     99 }
    100 void pretreat()//预处理 
    101 {
    102     memset(num,0,sizeof(num));//num[k]数组表示从2000年到k年,这么多个整年一天一天的出现了多少个9
    103     for(int year=2000;year<=9999;year++)
    104     {
    105         int ans=0;
    106         if(is_leap_year(year)) ans+=66;
    107         else ans+=65;
    108         
    109         int cnt=0;
    110         if(year%10 == 9) cnt++;
    111         if(year/10%10 == 9) cnt++;
    112         if(year/100%10 == 9) cnt++;
    113         if(year/1000 == 9) cnt++;
    114         cnt*=is_leap_year(year)?(366):(365);
    115          
    116         ans+=cnt;
    117         
    118         num[year]=num[year-1]+ans;
    119     }
    120 }
    121 int main()
    122 {
    123     pretreat();
    124     int t;
    125     scanf("%d",&t);
    126     while(t--)
    127     {
    128         scanf("%d%d%d%d%d%d",&st.y,&st.m,&st.d,&ed.y,&ed.m,&ed.d);
    129         if(st.y==ed.y)//情况① 
    130         {
    131             printf("%d
    ",calc(st.y ,st.m, st.d, ed.m, ed.d));
    132             continue;
    133         }
    134         else if(ed.y-st.y==1)//情况② 
    135         {
    136             printf("%d
    ",calc(st.y ,st.m, st.d, 12, 31)+calc(ed.y , 1, 1, ed.m, ed.d));
    137             continue;
    138         }
    139         else//情况③ 
    140         {
    141             int ans=num[ed.y-1]-num[st.y];
    142             ans+=calc(st.y ,st.m, st.d, 12, 31)+calc(ed.y , 1, 1, ed.m, ed.d);
    143             printf("%d
    ",ans);
    144             continue;
    145         }
    146     }
    147 }
  • 相关阅读:
    n个元素进栈,有几种出栈方式
    The following IP can be used to access Google website
    一个未排序整数数组,有正负数,重新排列使负数排在正数前面,并且要求不改变原来的 相对顺序 比如: input: 1,7,-5,9,-12,15 ans: -5,-12,1,7,9,15 要求时间复杂度O(N),空间O(1) 。
    当今世界最受人们重视的十大经典算法
    指针
    变量作用域和生存期
    一篇文章搞清spark内存管理
    Spark的Shuffle是怎么回事
    一篇文章搞清spark任务如何执行
    scala这写的都是啥?一篇文章搞清柯里化
  • 原文地址:https://www.cnblogs.com/dilthey/p/6837866.html
Copyright © 2011-2022 走看看