算法学习记录:[NOIP2016]回文日期

题目链接

https://ac.nowcoder.com/acm/contest/20960/1015

TLE代码

#include <iostream>

using namespace std;

const int N = 10;
int n, x, y;
int X[N], Y[N];
int get_day[] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

// 拆分数字
void num_to_arr(int num, int a[])
{
	int bit = 8;
	while (bit -- )
	{
		// cout << bit << ' ';
		a[bit] = num % 10, num /= 10;
	}
}

int qmi(int a, int b)
{
	int res = 1;
	for (; b; b >>= 1)
	{
		if ((b & 1)) res *= a;
		a = a * a; 
	}
	return res;
}

int arr_to_num(int a[], int bit, int beg)
{
	int res = 0, d = qmi(10, bit);
	for (int i = beg; i <= beg + bit; ++ i)
		res += a[i] * d, d /= 10;
	return res;
}

// 判断日期是否合法
bool is_right(int year, int mou, int day)
{ 	
	int flag = false; 
	int r_mou = get_day[mou];
	if (mou == 2 && ((!(year % 4) && (year % 100)) || !(year % 400)))	// 闰年,29天
		r_mou += 1;

	if (mou >= 1 && mou <= 12 && day >= 1 && day <= r_mou) flag = true;
	return flag;
}

bool is_w(int a[])
{
	for (int i = 0, j = 7; i < j; ++ i, -- j)
		if (a[i] != a[j]) return false;
	return true;
}
 

int main()
{
	cin >> x >> y;
	int cnt = 0;
	
	// 20110101
	// 20111231
	
	// 判断回文数,先判断日期是否和法再取年的相反
	for (int i = x; i <= y; ++ i)
	{
		num_to_arr(i, X);
		int year = arr_to_num(X, 3, 0),  mou = arr_to_num(X, 1, 4), day = arr_to_num(X, 1, 6);
		if (!is_right(year, mou, day)) continue;
		if (is_w(X)) cnt ++ ;
	}	

	cout << cnt << endl;
	return 0;
}	

AC代码

TLE代码会枚举所有的年月日,然后就爆炸了。
减少枚举次数,枚举所有的年,构造一个对于年来说的月、日的回文,再判断月、日是否合法。

错误原因

1.判断闰年判错了
2.没有考虑末尾月份是否大于当前月份,末尾日是否大于当前日

#include <iostream>
 
using namespace std;
 
const int N = 10;
int n, x, y;
int X[N], Y[N];
int get_day[] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
// 拆分数字
void num_to_arr(int num, int a[])
{
	int bit = 8;
	while (bit -- )
		a[bit] = num % 10, num /= 10;
}
 
int qmi(int a, int b)
{
	int res = 1;
	for (; b; b >>= 1)
	{
		if ((b & 1)) res *= a;
		a = a * a; 
	}
	return res;
}
 
int arr_to_num(int a[], int bit, int beg)
{
	int res = 0, d = qmi(10, bit);
	for (int i = beg; i <= beg + bit; ++ i)
		res += a[i] * d, d /= 10;
	return res;
}
 
// 判断日期是否合法
bool is_right(int year, int mou, int day)
{ 	
	int flag = false; 
	int r_mou = get_day[mou];
	if (mou == 2 && ((!(year % 4) && (year % 100)) || !(year % 400)))	// 闰年,29天
		r_mou += 1;
    
	if (mou >= 1 && mou <= 12 && day >= 1 && day <= r_mou) flag = true;

	return flag;
}
 
// 构造回文
void generate_year_day(int year)
{
	int bit = 4;
	while (bit -- )
		X[bit] = year % 10, year /= 10;
 
	for (int i = 0, j = 7; i < j; ++ i, -- j)
		X[j] = X[i];
}

int main()
{
	cin >> x >> y;
	int cnt = 0;	
 
	num_to_arr(x, X), num_to_arr(y, Y);
	
	// 20000101
	// 01234567
	// 20101231
 
	// 提出年,枚举所有年
	int st_year = arr_to_num(X, 3, 0), ed_year = arr_to_num(Y, 3, 0);
	int ed_mou = arr_to_num(Y, 1, 4), ed_day = arr_to_num(Y, 1, 6);
	
    for (int i = st_year; i <= ed_year; ++ i)
	{
		// 对年构造回文
		generate_year_day(i);

        // if (!is_w(X)) continue;
		int year = arr_to_num(X, 3, 0), mou = arr_to_num(X, 1, 4), day = arr_to_num(X, 1, 6);
        
        int flag = true;
        if (year >= ed_year)
        {
            if (year > ed_year) flag = false;
                if (flag && mou >= ed_mou) 
                {
                    if (mou > ed_mou) flag = false;

                    if (flag && day > ed_day) flag = false;
                }
        }
        if (!flag) continue;

		if (is_right(year, mou, day)) 
            cnt ++ ;
      
	}
	
	cout << cnt << endl;
	return 0;
}	
posted @ 2023-05-21 14:51  想个昵称好难ABCD  阅读(15)  评论(0编辑  收藏  举报