完全对称日

题目描述:

输出自公元纪年以来的完全对称日

 

讲题过程:

关键字:
一、日期
二、回文

1、生成日期,判断是否回文
2、生成一个回文,判断他是不是一个日期

1、生成日期,判断是否回文:
如何判断回文?
正着for和倒着for一样的
比如:
abcdefgh
for(i=1;i<=8;++i) 
    if(s[i]!=s[8-i+1]) 不是回文 
优化:判断一半的长度
for(i=1;i<=4;++i) 
    if(s[i]!=s[8-i+1]) 不是回文 

如何生成日期?
由8位数字组成
1、8个for循环,对生成的每一个8位数,判断他是不是1个日期
边界问题:年份到每一位的上限之后,对后面的数字有约束
月份:第5/6位是不是01——12
日:1、闰年的2月29天 2、 1月、3月……31天  3、30天
    年、月对日都有约束
麻烦,不用

改进:
生成年份:for 1——2020
生成月份 for 1——12
生成日: for 1——28/29.30.31

8位数放到数组里

2、生成一个回文,判断他是不是一个日期

如何判断是不是一个日期?
年、月、日?

分别提取出来

判断 
年<=2020 
月:月<=12
日:分三类
<=31
<=28  29
<=30

如何生成回文?
最开始想到生成1个四位数年份,镜像翻转
但忽略了日期并不一定是8位数
这样会漏下一些,比如10101,公元1年1月1日
生成年份1,镜像翻转得00011000
所以要对回文的长度进行讨论
如果回文是7位数,那么需要生成3位年份以及月份的第1位,镜像翻转前2位年份
如果回文是6位数,那么需要生成2位年份以及月份,镜像翻转2位年份和第1位月份
如果回文是5位数,那么需要生成1位年份以及月份,镜像翻转1位年份和2位月份

所以本思路就比较麻烦了


改进:不需要考虑闰月

若是8位:
XXXXPP29

92OOOOOO,年份超限

若是7位:

XXX0229

9220229,922年不是闰年

若是6位:

XX0229

9220XX,无法回文

若是5位:

X0229,无法回文

 

BUG:
边界问题,由于2020年只过了2个月加2天,所以存在边界问题,算到2019年,再额外加上1个即可(20200202)

梳理一下最终思路:

最终选择思路一:生成日期,判断是否回文
1、for 1——2019 生成年份
2、for 1——12 生成月份
3、for 1——30/31 生成日
4、放到一个数组里
5、判断是否回文,若回文,累加器+1
6、输出累加结果+1

 

代码:

'''
#include<stdio.h>

int len,s[9]; //数组保存日期,len记录长度 

int judge(int m) //判断月份天数 
{
	if(m==2) return 28;
	if(m==1 || m==3 || m==5 || m==7 || m==8 || m==10 || m==12) return 31;
	return 30;
}

void turn(int y,int m,int d) //将生成的日期放到数组里 
{
	//由于年份长度不确定,所以采用将他们倒着放进去,即20190812存为21809102 
	//正序倒序不影响回文的判定 
	len=0;
	if(d>=10) //日如果是个位数,要补1个0 
		while(d) s[++len]=d%10,d/=10;
	else s[++len]=d,s[++len]=0;
	if(m>=10) //月同上 
		while(m) s[++len]=m%10,m/=10;
	else s[++len]=m,s[++len]=0;
	while(y) s[++len]=y%10,y/=10;
}

int ok() //判断是否回文 
{
	int i,m=len/2;
	for(i=1;i<=m;++i)
		if(s[i]!=s[len-i+1]) return 0;
	return 1;
}

int main()
{
	int y,m,d,t,k,ans=0;
	for(y=1;y<=2019;++y) //年 ,最后加上20200202,所以上界是2019 
		for(m=1;m<=12;++m) //月 
		{ 
			t=judge(m); //得到月的天数上界 
			for(d=1;d<=t;++d) //日 
			{
				turn(y,m,d); //放到数组里 
				if(ok()) //如果回文 
				{
					ans++;
					for(k=1;k<=len;++k) printf("%d",s[k]); //输出这个世界完全数 
					printf("\n");
				}
			}
		}
	printf("20200202\n");  
	printf("%d",ans+1);
}
'''

 

### 回答1: 根据题目要求,美好子是一个共8位数字的完全对称,年份占4位,月份、份都是2位。因此,我们可以先判断该年份是否符合要求,即是否是4位数字。如果不是,则该年份不存在美好子。如果是4位数字,则需要判断该年份中是否存在美好子。 判断该年份中是否存在美好子,可以通过循环遍历该年份中的所有期,判断每个期是否符合要求。具体来说,可以从1月1开始,依次遍历到12月31,对于每个期,判断其是否是一个完全对称。如果存在一个完全对称,则该年份存在美好子;否则,该年份不存在美好子。 需要注意的是,判断一个期是否是完全对称,可以将该期转换为字符串,然后判断其是否与其反转后的字符串相等即可。例如,对于期20211202,其反转后的字符串为20211202,因此该期是一个完全对称。 综上所述,判断一个年份是否存在美好子的算法如下: 1. 判断该年份是否是4位数字,如果不是,则该年份不存在美好子,直接返回false。 2. 循环遍历该年份中的所有期,对于每个期,判断其是否是一个完全对称。 3. 如果存在一个完全对称,则该年份存在美好子,返回true;否则,该年份不存在美好子,返回false。 代码实现如下: def is_beautiful_day(year): # 判断年份是否是4位数字 if len(str(year)) != 4: return False # 循环遍历该年份中的所有期 for month in range(1, 13): for day in range(1, 32): # 判断期是否合法 if month in [4, 6, 9, 11] and day == 31: continue elif month == 2 and day > 29: continue elif month == 2 and day == 29 and not is_leap_year(year): continue # 将期转换为字符串 date_str = str(year) + str(month).zfill(2) + str(day).zfill(2) # 判断期是否是完全对称 if date_str == date_str[::-1]: return True # 不存在完全对称 return False def is_leap_year(year): # 判断是否是闰年 if year % 4 == and year % 100 != or year % 400 == : return True else: return False # 测试代码 print(is_beautiful_day(2021)) # False print(is_beautiful_day(2022)) # False print(is_beautiful_day(2023)) # False print(is_beautiful_day(2024)) # True print(is_beautiful_day(2025)) # False ### 回答2: 2021年12月2被认为是一个美好子,因为期20211202是一个完全对称的八位数字。这种期在我们的历中出现的频率非常罕见,因此人们视其为特殊的子。 对于给定的年份,我们需要判断该年是否有美好子。我们可以列出每个月份与份的组合,然后确定其中有多少个组合是完全对称的。 年份占4位,因此,一年中可能有以下情况: 1. 类似于2021年12月02这样的8位期; 2. 与第一种情况类似,但年份不同; 3. 与第一种情况类似,但月份与份交换; 4. 与第三种情况类似,但年份不同。 第一种情况只有1天,而第二、三、四种情况则有12天(1月1、2月2、3月3等)。因此,对于任何一年,一共有37个期是美好的。 因此,如果给定的年份中有任意一个期符合美好子的条件,那么该年就拥有美好子。如果没有,那么该年就没有美好子。 总之,美好子是一天特殊的子,由共8位数字的完全对称组成。在计算特定年份是否有美好子时,我们需要了解该年份中是否有任何符合条件的期。 ### 回答3: 在给定年份中,需要枚举每一个月份和期的组合,看是否存在对称。对于月份和期,我们可以将它们转化为字符串形式,然后判断字符串形式下的倒序是否和原串相同即可。下面是关于判断一个年份是否存在美好子的具体流程: 1.输入待判断的年份 y 2.设置标志位 flag = 0 3.枚举月份 m,m 的取值为 [1, 12] 4.枚举期 d,d 的取值为 [1, 31] 5.判断 (10 <= d <= 31 and m in {1, 3, 5, 7, 8, 10, 12}) 或 (10 <= d <= 30 and m in {4, 6, 9, 11}) 或 (m == 2 and (d <= 29 if y % 4 == 0 and y % 100 != 0 or y % 400 == 0 else d <= 28)) 是否成立,如果不成立则跳过该 (m, d) 的组合 6.将月份和期转化为字符串形式并倒序,判断其是否和直接转化为字符串后的结果相等,如果相等则输出 y, m, d,并将 flag 置为 1 7.如果 flag 仍然为 0,则输出不存在美好子的消息 完整的代码实现如下:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值