小白进阶之路-数一下9的个数-ZOj-3950

题目大意:如果我们用YYYY-MM-DD(例如,2020-04-25)的格式表示一个日期,您知道在Y1-M1-D1和Y2-M2-D2(包括两者)之间的所有日期中会出现多少个9吗?

 

 

初始想法:从第一个日期暴力到第二日期,发现实现很复杂。

转化思路:从2000 - 9999年暴力打表记录,特殊判断闰年的二月。

 

你要悄悄努力,争取绽放给别人你的成果~加油~

 

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<cstring>
#define ll long long
#define pb push_back
// #define memset(a,n) memset(a,n,sizeof(a))
#define mp make_pair
using namespace std;
const int maxn = 4e5 + 100;
void FAST()
{
    ios::sync_with_stdio(0);cin.tie(0);
}


int a[10000][13][32] = {0};
int p[2][12] = {31,28,31,30,31,30,31,31,30,31,30,31, // p[0] 非闰年
                31,29,31,30,31,30,31,31,30,31,30,31}; // p[1] 闰年


int get9(int x) // 得到数字中 9 的个数
{
    int ans = 0;
    while(x){
        if(x % 10 == 9) ans++;x /=  10;
    }
    return ans;
}


int ok(int x) // 检查是不是闰年
{
    if(x % 400 == 0 || ( x % 4 == 0 && x % 100)) return 1;
    return 0;
}

void solve() // 打表过程
{
    
    int ans = 0; // ans : 积累到现在 9 的个数
    for(int i = 2000;i < 10000;i++){ // i : 代表年份
        for(int j = 1;j <= 12;j++){ // j : 代表月份
            int cur = 28; // cur : 天数上限
            if(ok(i) && j == 2) cur = p[1][j-1]; // 如果闰年且2月,则 cur = 28;
            else cur = p[0][j-1]; // 一般情况下都一样
            for(int k = 1;k <= cur;k++) { // 天数
                int cnt = get9(i) + get9(j) + get9(k); // 当前日期的9的个数
                a[i][j][k] = cnt + ans;  // 到当前日期的 9 的个数 = 到上一天 9 的个数 + 这一天的 9 的个数
                ans = a[i][j][k]; // 保存昨天的 9 的个数
            }
        }
    }
}



int main()
{
    solve();
    int t ;scanf("%d",&t);
    while(t--){
        int Y1,M1,D1,Y2,M2,D2;
        scanf("%d%d%d%d%d%d",&Y1,&M1,&D1,&Y2,&M2,&D2);
        printf("%d\n",a[Y2][M2][D2] - a[Y1][M1][D1] + get9(Y1) + get9(M1) + get9(D1));// 两者相减去除了第一个日期的数量,需要重新计算
    }
    // system("pause");
}

 

posted @ 2020-04-26 11:39  Wise_4  阅读(191)  评论(0编辑  收藏  举报