小白进阶之路-数一下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"); }