题目及解析如下:
题目大致介绍:
第一题到第四题是结果填空,方法不限只要得到最后结果就行
第五题和第六题是代码填空题,主要考察算法基本功和编程基本功
第七题到第十题是编程题,要求编程解决问题
第一题 世纪末的星期
曾有邪教称1999年12月31日是世界末日。当然该谣言已经不攻自破。还有人称今后的某个世纪末的12月31日,如果是星期一则会....
有趣的是,任何一个世纪末的年份的12月31日都不可能是星期一!! 于是,“谣言制造商”又修改为星期日......
1999年的12月31日是星期五,请问:未来哪一个离我们最近的一个世纪末年(即xx99年)的12月31日正好是星期天(即星期日)?
请回答该年份(只写这个4位整数,不要写12月31等多余信息)
这个题可以使用Java中的Calendar类来做,考试的时候直接看API就行,平时了解一下就行了,代码如下:
1 import java.util.Calendar; 2 3 // 2299 4 public class t1 { 5 6 public static void main(String[] args) { 7 Calendar canlendar = Calendar.getInstance(); 8 for(int year = 1999; year < 5000; year+=100) { 9 canlendar.set(Calendar.YEAR, year); 10 canlendar.set(Calendar.MONTH, 11); // 12月 11 canlendar.set(Calendar.DAY_OF_MONTH, 31); 12 System.out.println(canlendar.toInstant()); // 输出年月日 13 System.out.println(canlendar.get(Calendar.DAY_OF_WEEK)); // 输出星期几 14 if(canlendar.get(Calendar.DAY_OF_WEEK) == 1) { 15 // 注: 1表示星期日 16 System.out.println(year); 17 break; 18 } 19 } 20 } 21 22 }
第二题 马虎的算式
小明是个急性子上小学的时候经常把老师写在黑板上的题目抄错了。 有一次老师出的题目是36 x 495 = ? 他却给抄成了396 x 45 = ?
但结果却很戏剧性他的答案竟然是对的 因为 36 * 495 = 396 * 45 = 17820 类似这样的巧合情况可能还有很多比如27 * 594 = 297 * 54
假设 a b c d e 代表1~9不同的5个数字注意是各不相同的数字且不含0 能满足形如ab * cde = adb * ce 这样的算式一共有多少种呢
一看就知道应该是用暴力法,5层for循环再加一个check就行:
1 // 142 2 3 public class t2 { 4 5 public static void main(String[] args) { 6 int res = 0; 7 for (int a = 1; a <= 9; a++) { 8 for (int b = 1; b <= 9; b++) { 9 for (int c = 1; c <= 9; c++) { 10 for (int d = 1; d <= 9; d++) { 11 for (int e = 1; e <= 9; e++) { 12 if (b != a && c != b && c != a && d != c && d != b && d != a && e != d && e != c && e != b 13 && e != a) { 14 if (((a * 10 + b) * (c * 100 + d * 10 + e)) == ((a * 100 + d * 10 + b) * (c * 10 + e))) { 15 res++; 16 } 17 } 18 } 19 } 20 } 21 } 22 } 23 24 System.out.println(res); 25 } 26 27 }
注:这种题记得输出结果进行验证一下!细节很重要!
第三题 振兴中华
小明参加了学校的趣味运动会,其中的一个项目是:跳格子 地上画着一些格子,每个格子里写一个字,如下所示:(也可参见p1.jpg)
从我做起振
我做起振兴
做起振兴中
起振兴中华
比赛时,先站在左上角的写着“从”字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。
要求跳过的路线刚好构成“从我做起振兴中华”这句话。
请你帮助小明算一算他一共有多少种可能的跳跃路线呢?
答案是一个整数,请通过浏览器直接提交该数字。注意:不要提交解答过程,或其它辅助说明类的内容
用递归,代码如下:
1 // 35 2 3 public class t3 { 4 5 public static int f(int r, int c) { 6 if (r == 3 || c == 4) { 7 return 1; 8 } 9 return f(r + 1, c) + f(r, c + 1); 10 } 11 12 public static void main(String[] args) { 13 System.out.println(f(0, 0)); 14 } 15 16 }
第四题 黄金连分数
黄金分割数0.61803... 是个无理数,这个常数十分重要,在许多工程问题中会出现。有时需要把这个数字求得很精确。
言归正传,我们如何求得黄金分割数的尽可能精确的值呢?有许多方法。
比较简单的一种是用连分数:
1
黄金数 = ---------------------
1
1 + -----------------
1
1 + -------------
1
1 + ---------
1 + ...
这个连分数计算的“层数”越多,它的值越接近黄金分割数。
请你利用这一特性,求出黄金分割数的足够精确值,要求四舍五入到小数点后100位。
小数点后3位的值为:0.618
小数点后4位的值为:0.6180
小数点后5位的值为:0.61803
小数点后7位的值为:0.6180340
(注意尾部的0,不能忽略)
你的任务是:写出精确到小数点后100位精度的黄金分割值。
注意:尾数的四舍五入! 尾数是0也要保留!
显然答案是一个小数,其小数点后有100位数字,请通过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。
解题思路:
可以化为求斐波那契数列相邻两项的比值:
但是注意直接用double精度会不够,因此我们可以使用BigInteger类和BigDecimal类:
1 import java.math.BigDecimal; 2 import java.math.BigInteger; 3 4 public class t4 { 5 6 public static void main(String[] args) { 7 BigInteger a = BigInteger.ONE; 8 BigInteger b = BigInteger.ONE; 9 for (int i = 3; i < 500; i++) { 10 BigInteger t = b; 11 b = a.add(b); 12 a = t; 13 } 14 BigDecimal divide = new BigDecimal(a, 110).divide(new BigDecimal(b, 110), BigDecimal.ROUND_HALF_DOWN); 15 System.out.println(divide.toPlainString().substring(0, 103)); 16 } 17 18 // 0.61803398874989484820458683436563811772030917980576286213544862270526046281890244969233401224637257135 19 // 0.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748 20 // 0.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748 21 22 // answer: 23 // 0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375 24 25 }
第五题 有理数类
1 // 有理数类 2 3 // 有理数就是可以表示为两个整数的比值的数字。一般情况下,我们用近似的小数表示。但有些时候, 4 // 不允许出现误差,必须用两个整数来表示一个有理数。 5 // 这时,我们可以建立一个“有理数类”,下面的代码初步实现了这个目标。为了简明,它只提供了 6 // 加法和乘法运算。 7 8 // 使用该类的示例: 9 // Rational a = new Rational(1,3); 10 // Rational b = new Rational(1,6); 11 // Rational c = a.add(b); 12 // System.out.println(a + "+" + b + "=" + c); 13 14 public class t5 { 15 static class Rational { 16 private long ra; 17 private long rb; 18 19 private long gcd(long a, long b) { 20 if (b == 0) 21 return a; 22 return gcd(b, a % b); 23 } 24 25 public Rational(long a, long b) { 26 ra = a; 27 rb = b; 28 long k = gcd(ra, rb); 29 if (k > 1) { // 需要约分 30 ra /= k; 31 rb /= k; 32 } 33 } 34 35 // 加法 36 public Rational add(Rational x) { 37 // return ________________________________________; //填空位置 38 return new Rational(ra * x.rb + rb * x.ra, rb * x.rb); 39 } 40 41 // 乘法 42 public Rational mul(Rational x) { 43 return new Rational(ra * x.ra, rb * x.rb); 44 } 45 46 public String toString() { 47 if (rb == 1) 48 return "" + ra; 49 return ra + "/" + rb; 50 } 51 } 52 53 public static void main(String[] args) { 54 Rational a = new Rational(1, 3); 55 Rational b = new Rational(1, 6); 56 Rational c = a.add(b); 57 System.out.println(a + "+" + b + "=" + c); 58 59 Rational a1 = new Rational(1, 3); 60 Rational b1 = new Rational(1, 3); 61 Rational c1 = a.add(b1); 62 System.out.println(a1 + "+" + b1 + "=" + c1); 63 } 64 65 }
第六题 三部排序
1 // 三部排序 2 // 对一个整型数组中的数字进行分类排序:使得负数都靠左端,正数都靠右端,0在中部。 3 // 注意问题的特点是: 4 // 负数区域和正数区域内并不要求有序。可以利用这个特点通过1次线性扫描就结束战斗!! 5 6 public class t6 { 7 static void sort(int[] x) 8 { 9 int p = 0; 10 int left = 0; 11 int right = x.length-1; 12 13 while(p<=right){ 14 if(x[p]<0){ 15 int t = x[left]; 16 x[left] = x[p]; 17 x[p] = t; 18 left++; 19 p++; 20 } 21 else if(x[p]>0){ 22 int t = x[right]; 23 x[right] = x[p]; 24 x[p] = t; 25 right--; 26 } 27 else{ 28 p++; //代码填空位置 29 } 30 } 31 } 32 }
第七题 错误票据
思路:
处理输入比较麻烦,可以用ArrayList来动态添加来保存输入的数,然后先用sort排序一下,从小到大排,排完后枚举判断即可
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.Scanner; 4 5 // 错误票据 6 // 某涉密单位下发了某种票据,并要在年终全部收回。 7 // 8 // 每张票据有唯一的ID号。全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。 9 // 10 // 因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。 11 // 12 // 你的任务是通过编程,找出断号的ID和重号的ID。 13 // 14 // 假设断号不可能发生在最大和最小号。 15 // 16 // 要求程序首先输入一个整数N(N<100)表示后面数据行数。 17 // 接着读入N行数据。 18 // 每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000) 19 // 每个整数代表一个ID号。 20 // 21 // 要求程序输出1行,含两个整数m n,用空格分隔。 22 // 其中,m表示断号ID,n表示重号ID 23 // 24 // 25 // 26 //例如: 27 //用户输入: 28 //2 29 //5 6 8 11 9 30 //10 12 9 31 //则程序输出: 32 //7 9 33 // 34 //再例如: 35 //用户输入: 36 //6 37 //164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196 38 //172 189 127 107 112 192 103 131 133 169 158 39 //128 102 110 148 139 157 140 195 197 40 //185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190 41 //149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188 42 //113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119 43 //则程序输出: 44 //105 120 45 46 public class t7 { 47 48 private static Scanner input; 49 50 public static void main(String[] args) { 51 input = new Scanner(System.in); 52 ArrayList list = new ArrayList(); 53 54 System.out.println(": "); 55 56 int N = input.nextInt(); 57 input.nextLine(); // 去掉整数后面的换行符 58 for (int i = 0; i < N; i++) { 59 String line = input.nextLine(); 60 String[] split = line.split(" "); 61 for (int j = 0; j < split.length; j++) { 62 list.add(Integer.parseInt(split[j])); 63 } 64 } 65 66 // System.out.println(list.size()); 67 68 Collections.sort(list); // 对集合进行排序 69 int a = 0, b = 0; // a接收断号的 b接收重号的 70 for (int i = 1; i < list.size(); i++) { 71 int cur = (int) (list.get(i)); 72 int pre = (int) (list.get(i - 1)); 73 if (cur - pre == 2) { 74 a = (int)(list.get(i)) - 1; 75 } 76 if (cur - pre == 0) { 77 b = (int)(list.get(i)); 78 } 79 } 80 System.out.println(a + " " + b); 81 } 82 83 }
第八题 幸运数 =》 太难 看不懂 直接放弃
第九题 带分数
代码如下:
1 import java.util.Scanner; 2 3 // 问题描述 4 // 100 可以表示为带分数的形式:100 = 3 + 69258 / 714。 5 // 还可以表示为:100 = 82 + 3546 / 197。 6 // 注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。 7 // 8 // 类似这样的带分数,100 有 11 种表示法。 9 // 10 // 输入格式 11 // 从标准输入读入一个正整数N (N<1000*1000) 12 // 13 // 输出格式 14 // 程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。 15 // 16 // 注意:不要求输出每个表示,只统计有多少表示法! 17 // 18 // 样例输入1 19 // 100 20 // 样例输出1 21 // 11 22 // 样例输入2 23 // 105 24 // 样例输出2 25 // 6 26 27 public class t9 { 28 public static int res = 0; 29 public static int N = 0; 30 private static Scanner input; 31 32 public static void main(String[] args) { 33 input = new Scanner(System.in); 34 System.out.println(); // 提交代码的时候注释 35 N = input.nextInt(); 36 int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 37 f(0, arr); 38 System.out.println(res); 39 } 40 41 // i: 确认某一个全排列的第k位 42 private static void f(int k, int[] arr) { 43 if (k == 9) { 44 check(arr); 45 return; 46 } 47 for (int i = k; i < arr.length; i++) { 48 int temp = arr[k]; 49 arr[k] = arr[i]; 50 arr[i] = temp; 51 f(k + 1, arr); // 选定第k位移交下一层确认k+1位 52 temp = arr[k]; 53 arr[k] = arr[i]; 54 arr[i] = temp; 55 } 56 57 } 58 59 // 枚举加号和乘号的位置 60 private static void check(int[] arr) { 61 for (int i = 1; i <= 7; i++) { 62 // 遍历生成第一个数 63 int num1 = toInt(arr, 0, i); 64 if (num1 >= N) { 65 return; 66 } 67 for (int j = 1; j <= 8 - i; j++) { 68 // 遍历生成第二个、第三个数 69 int num2 = toInt(arr, i, j); 70 int num3 = toInt(arr, i + j, 9 - i - j); 71 if (num2 % num3 == 0 && num1 + num2 / num3 == N) { 72 res++; 73 } 74 } 75 } 76 77 } 78 79 private static int toInt(int[] arr, int pos, int len) { 80 // 将数组中的数转换成整数 81 int t = 1; 82 int ans = 0; 83 for (int i = pos + len - 1; i >= pos; i--) { 84 ans += arr[i] * t; 85 t *= 10; 86 } 87 88 return ans; 89 } 90 91 }
第十题 连号区间数