2021-04-19

##20210419 D

题意

给定t个样例,每个样例有两个日期(格式为Y,M,D,表示为年月日),输出两个日期之间的所有日期的年月日组成的字符串中含有"202"的日期的字符串的个数。

思路

  1. 打表求出2000/01/01与所有日期之间的符合要求的日期的个数a[Y][M][D]。求法:从2000/01/01遍历到9999/12/31。设置一个c记录已经有多少日期符合要求,假设已经遍历到Y/M/D,此时c就是Y/M/D前一天到2000/01/01中所有符合要求的日期的个数。判断当前日期的字符串是否符合要求,符合则c++。此时的c就是2000/01/01到Y/M/D中所有符合要求的日期的个数。
  2. 对于每个样例都有两个日期Date1:y1,m1,d1和Date2:y2,m2,d2,求这个区间内的符合要求的日期的个数,则我们只需要求a[y2][m2][d2]减去a[Date1前一天]。
  3. 因为Date1前一天的可能会很难求(比如2021/01/01的前一天是2020/12/31),所以我们转为求cnt=a[y2][m2][d2]-a[y1][m1][d1]。然后判断y1,m1,d1组成的字符串是不是符合要求的字符串:
    • 如果符合,说明此时a[y1][m1][d1]比a[Date1]多1,说明多减了一个1,所以cnt加1。
    • 如果不符合,说明此时a[y1][m1][d1] == a[Date1],所以c不需要改变。
  4. 注意:这一题如果暴力,每次都重新求一遍会超时。

代码

#include<iostream>
#include<sstream>
#include<string>
using namespace std;


int a[10000][13][32];                                  //用于储存打表信息


int main()
{
	int y1, y2, m1, m2, d1, d2;
	y1 = 2000;
	m1 = 1;
	d1 = 1;
	y2 = 9999;
	m2 = 12;
	d2 = 31;
	int c = 0;
	for (int i = y1; i <= y2; i++)                      //打表
	{
		int j = 1;
		int j1 = 12;
		//if (i == y1) j = m1;
		//if (i == y2) j1 = m2;
		for (; j <= j1; j++)
		{
			int k = 1;
			int k1 = 31;
			if (j == 4 || j == 6 || j == 9 || j == 11)
				k1 = 30;
			if (j == 2)
			{
				if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
				{
					k1 = 29;
				}
				else
					k1 = 28;
			}
			//if (i == y1 && j == m1) k = d1;
			//if (i == y2 && j == m2) k1 = d2;
			for (; k <= k1; k++)
			{
				int p = i * 10000;
				p += (j * 100);
				p += k;
				string b = to_string(p);                        //将整型转化为字符型
				if (b.find("202") != string::npos)//查找是否含有子串"202"
				{
					c++;
				}
				a[i][j][k] = c;                                //记录
			}
		}

	}


	int t;

	cin >> t;


	while (t--)
	{
		c = 0;
		cin >> y1 >> m1 >> d1 >> y2 >> m2 >> d2;
		string t;
		int p = y1 * 10000;
		p += (m1* 100);
		p += d1;
		string b = to_string(p);
		t=to_string(p);

		c = a[y2][m2][d2] - a[y1][m1][d1];
		if (t.find("202") != string::npos)
		{
			c++;
		}

		cout << c << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值