题目:
要编写六个函数:
1.从int转换为指定位数的string的函数
string i2s(int x,int w){
string res;
while(x){
res+=x%10+'0';
x/=10;
}
while(res.length()<w){
res+='0';
}
reverse(res.begin(),res.end());
return res;
}
x为该书的int类型,w为该数字的位数,先设要转换的类型string res,用‘+’符号对该字符串进行操作,提取数字加上‘0’的ASCII码就是该数字的字符串的字符形式
2.从string转换为int的函数
int s2i(string x){
int res=0;
for(auto & i : x )res=res*10+i-'0';
return res;
}
使用了auto循环用i 对字符串的每位进行提取,提取的ASCII码减去‘0’的ASCII码就是该数字(非字符串形式),递归的方式将(按0.。。。n)加权的形式将之转换
3.判断闰年的函数
bool isLeapYear(int year){
return (year%4==0&&year%100)||(year%400==0);
}
判断是否是闰年的条件是 该年能整除4不能整除100, 或者 能整除400
4.判断日期是否合法的函数
bool isok(int year,int month,int day){
int nums[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(year))nums[2]=29;
return day<=nums[month];
}
该函数有三个接收口(年,月,日),为方便循环的进行我们将nums的第一个数设为0,并通过是否为闰年的判断二月为多少天,是否合法的客观条件是每个月不可能超过最大天数,所以返回day<=nums[month]
5.判断字符串是否是回文的函数
bool isPa1(string s){
for(int i=0;i<s.length()/2;++i){
if(s[i]!=s[s.length()-1-i])return false;
}
return true;
}
取8位回文数的一半作为循环的判断条件,对半相等则返回true,不相等则返回false
6.判断字符串是否是ABABBABA型回文的函数
bool isPa2(string s){
if(!isPa1(s))return false;
return s[0]==s[2]&&s[1]==s[3];
}
符合isPa1函数的字符串,已经确定对半相等,所以我们先调用isPa1函数,再判断前四位两两相等即可
###该题考察的是模拟
###做这样的题我们要有严谨的逻辑,保持清醒的头脑,看着整体思路挺多,其实本质是相近的,按照我们解复杂数学题的方法:将大问题拆解为若干个小问题(比如:2,3,4,5条就是一个根据客观规律遍历的问题 1,6条就是考虑到了分析过程中需要转换类型的问题 7条基本工作已经做完了,看清题意,判断输出就完事了)
#include<bits/stdc++.h>
using namespace std;
//字符串类型转换为整型函数
int s2i(string x){
int res=0;
for(auto & i : x )res=res*10+i-'0';
return res;
}
//整型转换为字符串类型函数(缺位自动补0)
string i2s(int x,int w){
string res;
while(x){
res+=x%10+'0';
x/=10;
}
while(res.length()<w){
res+='0';
}
reverse(res.begin(),res.end());
return res;
}
//判断是否是闰年
bool isLeapYear(int year){
return (year%4==0&&year%100)||(year%400==0);
}
//判断日期是否合法
bool isok(int year,int month,int day){
int nums[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(year))nums[2]=29;
return day<=nums[month];
}
//判断是否是回文1
bool isPa1(string s){
for(int i=0;i<s.length()/2;++i){
if(s[i]!=s[s.length()-1-i])return false;
}
return true;
}
//判断是否是回文2
bool isPa2(string s){
if(!isPa1(s))return false;
return s[0]==s[2]&&s[1]==s[3];
}
int main(){
string s;cin>>s;
bool ans1=false,ans2=false;
int year=s2i(s.substr(0,4)),month=s2i(s.substr(4,2)),day=s2i(s.substr(6,2));
for(int i=year;i<=9999;++i){
for(int j=1;j<=12;++j){
if(i==year&&j<month)continue;
for(int k=1;k<=31;++k){
if(i==year&&j==month&&k<=day)continue;
//是否合法
if(!isok(i,j,k))continue;
//拼接回去
string date=i2s(i,4)+i2s(j,2)+i2s(k,2);
//判断1
if(!ans1&&isPa1(date)){
cout<<date<<'\n';
ans1=true;
}
//判断2
if(!ans2&&isPa2(date)){
cout<<date<<'\n';
ans2=true;
}
}
}
}
return 0;
}
整体思路:
- 输入字符串,利用substr(下标,位数)字符串截取函数提取出年,月,日,再用s2i函数转换为int类型都存储起来
- 开始按照客观规律将年从输入的年份开始遍历到9999
- 内部接着循环月同理还是根据客观规律第一次要从你输入的月份开始遍历,所以等于该年份 且 小于输入月份的 一律continue
- 内部接着循环日同理还是根据客观规律第一次要从你输入的日开始遍历,所以等于该年份 且 等于该月份 且 小于输入日的 一律continue
- 接着我们在年,月,日的循环中判断是不是合法日期,将不符合客观规律的超过当月天数的筛去,调用isok函数,不是一律continue
- 是合法日期我们再用i2s函数转成string类型并用‘+’连接成一个字符串
- 接下来据题意调用isPa1和isPa2判断是否是该类型的回文数,是则输出,另外题意要的只是出现第一次的两个类型的回文数,所以我们再在前面设一个bool类型的ans1和ans2做判断是否已有满足条件的回文数
###重要的是我们自己想出要解决这个问题 要干什么,如何干 的这种思维