练习题基于《C/C++程序设计竞赛真题实战特训教程(图解版)》
目录
1.1 卡片
题目描述
代码实现
题解笔记
总评
注意点
重点解释
1.2 回文日期
题目描述
输入描述
输出描述
代码实现
题解笔记
总评
注意点
重点解释
1.1 卡片
题目描述
小蓝有很多数字卡片,每张卡片上都是数字 0 到 9。小蓝准备用这些卡片来拼一些数,他想从 1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。小蓝想知道自己能从 1 拼到多少。例如,当小蓝有 30 张卡片,其中 0 到 9 各 3 张,则小蓝可以拼出 1 到 10,但是拼 11 时卡片 1 已经只有一张了,不够拼出 11。
现在小蓝手里有 0 到 9 的卡片各 2021 张,共 20210 张,请问小蓝可以从 1 拼到多少?
代码实现
public class Main {public static void main(String[] args) {int a[]=new int [10];//i:表示最后一个数字;j:表示去除最后一个位数后剩下的数int i,j;//从后往前,依次把最后一位的数字计入数组for(i=1;;i++){a[i%10]++;j=i/10;while(j>0){a[j%10]++;j=j/10;}//卡片1是最先被消耗完的,故只需判断1被消耗完的情况if(a[1]>2021){i=i-1;//判断条件是消耗完,故输出的值需减一break;}}System.out.println(i);}
}
题解笔记
总评
题目难度不大,重点在于理解题目的核心意思,找出卡片消耗完前最后一个拼成的数字。
注意点
- 理解卡片数字1是最先被消耗完的
- 思考如何记录每个拼成的数字的每个位数的内容(即每个拼成的数字消耗卡片的内容)
重点解释
用j记录当前拼成的数字去除个位数后的数字,并将去除的个位数计入数组中,重复操作,数组的元素即不同卡片的个数。
1.2 回文日期
题目描述
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。
输入描述
输入包含一个八位整数 N,表示日期。
对于所有评测用例,10000101≤N≤89991231,保证 N 是一个合法日期的 8 位数表示。
输出描述
输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。
代码实现
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int data = sc.nextInt();boolean flag = false;for (int i = data + 1; i <= 99991231; i++) {String str = String.valueOf(i);String year = str.substring(0, 4);String month = str.substring(4, 6);String day = str.substring(6, 8);if (!isValidDate(year,month,day)) {continue;}if(isHui(year,month,day)&& !flag) {System.out.println(i);flag = true;}if(isABHui(year,month,day)) {System.out.println(i);break;}}sc.close();}//判断日期是否符合常识public static Boolean isValidDate(String y, String m, String d) {int year=Integer.parseInt(y);int month=Integer.parseInt(m);int day=Integer.parseInt(d);if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {if ((year % 4 == 0 && year % 100 != 0 )|| year % 400 == 0) {if (month == 2) return day <= 29;else if (month == 4 || month == 6 || month == 9 || month == 11) {return day <= 30;} else return true;}else if(month == 2) return day < 29;else if (month == 4 || month == 6 || month == 9 || month == 11) {return day <= 30;} else return true;}return false;}//判断是否为回文日期public static boolean isHui(String y, String m, String d) {return y.charAt(3) == m.charAt(0) && y.charAt(2) == m.charAt(1) && y.charAt(1) == d.charAt(0) && y.charAt(0) == d.charAt(1);}//判断是否为ABABBABA型的回文日期public static boolean isABHui(String y, String m, String d) {if(isHui(y,m,d)) {return y.charAt(0) == y.charAt(2) && y.charAt(1) == y.charAt(3);}return false;}
}
题解笔记
总评
题目难度不大,重点在于理解题目的核心意思。注意不要被输入描述误导,输出的日期是可以大于89991231的!!!
注意点
- 确定日期要符合常识,月份在1到12之间,闰年和平年2月的天数不同等
- ABAB型的回文日期是回文日期的特殊形态,所以满足ABAB型前,可能不止一个正常的回文日期。
- 输入描述是指评测用例小于等于89991231,不是输出!!!
重点解释
在日期符合常识的情况下,判断回文条件是否满足。判断条件是否满足前,其实可以直接用数学的思想把8位数储存进不同变量,相对会更容易一点。