Bootstrap

洛谷 P2010 [NOIP2016 普及组] 回文日期(代码仅16行!!)

好吧,感觉自己再一次被坑了

题意

给你两个日期ab(八位数YYYYMMDD),求这两个日期中间(包括这两个日期本身)有多少个日期是回文的。
例如 输入:20000101 20101231输出:22001100220100102是符合要求的)

思路1

第一个想到的是直接枚举ab之间的整数,判断是否为合法的日期,再判断是否为回文串。

#include<bits/stdc++.h>
using namespace std;
int b,e;
long long ans=0;
bool judge(int date){
   int s=0,t=date;
   while(t>0){
   	s=s*10+t%10;
   	t/=10;
   }
   if(date==s) return true;
   else return false;
}
int day(int year,int month){
   if(month<8){
   	if(month%2==1) return 31;
   	else if(month==2){
   		if(year%100!=0&&year%4==0) return 29;
   		else return 28;
   	}
   	else return 30;
   }
   if(month>=8){
   	if(month%2==0) return 31;
   	else return 30;
   }
}
bool judge2(int date){
   int y=date/10000;
   int m=date/100%100;
   int d=date%100;
   if(d>day(y,m)||d<1) return false;
   if(m>12||m<1) return false;
   return true;
}
int main(){
   cin>>b>>e;
   if(b==e){
   	cout<<judge(b)<<endl;
   	return 0;
   }
   for(int num=b;num<=e;num++)
   	if(judge2(num))//判日期合法
   		if(judge(num))//判回文
   			ans++;
   cout<<ans<<endl;
   return 0;
}

这其实是我两年之前写的代码,当时我才学了c++没多久,代码也是又臭又长。

思路2

如果换一种枚举方式,先保证他是回文串,月份和日期合法,再判断日期是否在ab之间,就会简单很多。我们枚举月和日,再把年份通过回文算出来,比如10月12日,也就是1012,对应的年份就是2101,拼起来是21011012,是回文串。
这个时候会遇到一个问题:闰年怎么办?
别慌,闰年与平年唯一的不同就是2月29号,变成数字串0229,它所对应的年份是9220,确实是闰年,所以只要最后判断一下92200229是否在ab之间就行了

#include<bits/stdc++.h>
using namespace std;
int a,b,ans,D[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main(){
	cin>>a>>b;
	for(int i=1;i<=12;i++)
		for(int j=1;j<=D[i];j++){
			int y=j%10*1000+j/10*100+i%10*10+i/10;
			//将月和日拆分成一个个数字后再倒着组合成年份
			int date=y*10000+i*100+j;
			if(date>=a&&date<=b) ans++; 
		}
	int date=92200229;
	if(date>=a&&date<=b) ans++;
	printf("%d\n",ans);
	return 0;
} 

这就舒服多了嘛!(觉得自己特别聪明)

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;