目录
1 马虎的算式
2 黄金连分数
3 有理数类
4 幸运数
5 连号区间数
前言:以下试题解答代码部分仅供参考,若有不当之处,还请路过的同学提醒一下~
1 马虎的算式
标题: 马虎的算式 小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。 有一次,老师出的题目是: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 这样的算式一共有多少种呢? 请你利用计算机的优势寻找所有的可能,并回答不同算式的种类数。 满足乘法交换律的算式计为不同的种类,所以答案肯定是个偶数。 答案直接通过浏览器提交。 注意:只提交一个表示最终统计种类数的数字,不要提交解答过程或其它多余的内容。 142
方法1(暴力枚举): import java.util.ArrayList; import java.util.Collections; public class Main { public static int count = 0; //判断A和B是否是否1~9中不同的5个数字组成 public boolean judge(int A, int B) { ArrayListlist = new ArrayList (); while(A > 0) { list.add(A % 10); A = A / 10; } while(B > 0) { list.add(B % 10); B = B / 10; } Collections.sort(list); for(int i = 1;i < list.size();i++) { if(list.get(i - 1) == 0 || list.get(i - 1) == list.get(i)) return false; } return true; } public void printResult() { for(int a = 10;a < 100;a++) { for(int b = 100;b < 1000;b++) { if(judge(a, b)) { int a1 = a % 10; int a2 = a / 10; int b1 = b % 10; int b2 = b / 10 % 10; int b3 = b / 100; if(a * b == (a2*100 + b2*10 + a1) * (b3*10 + b1)) { count++; } } } } } public static void main(String[] args) { Main test = new Main(); test.printResult(); System.out.println(count); } }
方法2(dfs全排列枚举): import java.util.ArrayList; public class Main1 { public static int count = 0; public void check(ArrayListlist) { int a = list.get(0); int b = list.get(1); int c = list.get(2); int d = list.get(3); int e = list.get(4); int num1 = (a*10 + b) * (c*100 + d*10 + e); int num2 = (a*100 + d*10 + b) * (c*10 + e); if(num1 == num2) count++; return; } //dfs求取1~9中随机五个不同数字的全排列 public void dfs(ArrayList list, int step) { if(step == 5) { check(list); return; } else { for(int i = 1;i < 10;i++) { if(list.contains(i)) continue; list.add(i); dfs(list, step + 1); list.remove(list.size() - 1); } } return; } public static void main(String[] args) { Main1 test = new Main1(); ArrayList list = new ArrayList (); test.dfs(list, 0); System.out.println(count); } }
2 黄金连分数
标题: 黄金连分数 黄金分割数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位数字,请通过浏览器直接提交该数字。 注意:不要提交解答过程,或其它辅助说明类的内容。 0.6180339887498948481971959525508621220510663574518538453723187601229582821971784348083863296133320592(求取fib(48) / fib(49)的精度) 0.6180339887498948482045868343656381177203091798057628621354486227052604628189024496923340122463725714(求取fib(198)/fib(199)的精度) 0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375(求取fib(49998)/fib(49999)的精度) 此处,个人建议求取精度的问题,尽量做到当前自己能够使用计算机算的最大精度,所以最好选择fib(49998)/fib(49999)的结果。 轻易可知fib(100)以上的数基本上已经超过long型整数的范围了,此处可以借用大整数类型完成更加精确的计算。
import java.math.BigDecimal; import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger[] A = new BigInteger[50000]; A[0] = new BigInteger("0"); A[1] = new BigInteger("1"); for(int i = 2;i < 50000;i++) { A[i] = A[i - 1].add(A[i - 2]);//迭代求取斐波那契数(i值越大,求取结果精度越大) } BigDecimal a = new BigDecimal(A[49998]); BigDecimal b = new BigDecimal(A[49999]); System.out.println(a.divide(b, 100, BigDecimal.ROUND_HALF_UP)); } }
3 有理数类
标题:有理数类 有理数就是可以表示为两个整数的比值的数字。一般情况下,我们用近似的小数表示。但有些时候,不允许出现误差,必须用两个整数来表示一个有理数。 这时,我们可以建立一个“有理数类”,下面的代码初步实现了这个目标。为了简明,它只提供了加法和乘法运算。 class Rational { private long ra; private long rb; private long gcd(long a, long b){ if(b==0) return a; return gcd(b,a%b); } public Rational(long a, long b){ ra = a; rb = b; long k = gcd(ra,rb); if(k>1){ //需要约分 ra /= k; rb /= k; } } // 加法 public Rational add(Rational x){ return ________________________________________; //填空位置 } // 乘法 public Rational mul(Rational x){ return new Rational(ra*x.ra, rb*x.rb); } public String toString(){ if(rb==1) return "" + ra; return ra + "/" + rb; } } 使用该类的示例: Rational a = new Rational(1,3); Rational b = new Rational(1,6); Rational c = a.add(b); System.out.println(a + "+" + b + "=" + c); 请分析代码逻辑,并推测划线处的代码,通过网页提交 注意:仅把缺少的代码作为答案,千万不要填写多余的代码、符号或说明文字!! new Rational(x.ra*rb + ra*x.rb, x.rb*rb)
4 幸运数
标题:幸运数 幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成。 首先从1开始写出自然数1,2,3,4,5,6,.... 1 就是第一个幸运数。 我们从2这个数开始。把所有序号能被2整除的项删除,变为: 1 _ 3 _ 5 _ 7 _ 9 .... 把它们缩紧,重新记序,为: 1 3 5 7 9 .... 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11, 17, ... 此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,...) 最后剩下的序列类似: 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, ... 本题要求: 输入两个正整数m n, 用空格分开 (m < n < 1000*1000) 程序输出 位于m和n之间的幸运数的个数(不包含m和n)。 例如: 用户输入: 1 20 程序输出: 5 例如: 用户输入: 30 69 程序输出: 8 资源约定: 峰值内存消耗(含虚拟机) < 64M CPU消耗 < 2000ms 请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。 所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。 注意:主类的名字必须是:Main,否则按无效代码处理。
import java.util.ArrayList; import java.util.Scanner; public class Main { public void printResult(int m, int n) { ArrayListlist = new ArrayList (); list.add(-1); //第0位存-1,后面才开始存幸运数,方便后面删除操作 for(int i = 1;i < n;i++) { if(i % 2 == 0) continue; list.add(i); } int count = 2; //开始遍历的幸运数位置 while(true) { int start = list.get(count); ArrayList list1 = new ArrayList (); list1.add(-1); for(int i = 1;i < list.size();i++) { if(i % start == 0) continue; else { list1.add(list.get(i)); } } list = list1; count++; if(count > list.size() - 1) break; } list.remove(0); //删除第0位-1情况 int i = 0; for(;i < list.size();i++) { if(list.get(i) > m) break; } int result = list.size() - i; System.out.println(result); } public static void main(String[] args) { Main test = new Main(); Scanner in = new Scanner(System.in); int m = in.nextInt(); int n = in.nextInt(); test.printResult(m, n); } }
5 连号区间数
标题:连号区间数 小明这些天一直在思考这样一个奇怪而有趣的问题: 在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是: 如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。 当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。 输入格式: 第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。 第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。 输出格式: 输出一个整数,表示不同连号区间的数目。 示例: 用户输入: 4 3 2 4 1 程序应输出: 7 用户输入: 5 3 4 2 5 1 程序应输出: 9 解释: 第一个用例中,有7个连号区间分别是:[1,1], [1,2], [1,3], [1,4], [2,2], [3,3], [4,4] 第二个用例中,有9个连号区间分别是:[1,1], [1,2], [1,3], [1,4], [1,5], [2,2], [3,3], [4,4], [5,5] 资源约定: 峰值内存消耗(含虚拟机) < 64M CPU消耗 < 5000ms 请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。 所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。 注意:主类的名字必须是:Main,否则按无效代码处理。
import java.util.Scanner; public class Main { /* * 这题的重点在于题意的理解,题意理解了,解答就会很简单 *核心: 如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素) * 递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。 * 那么就是说,在给定的一个全排列中A[L]~A[R]之间未排序,如果经过递增排序处理后 * 发现,A[L]~A[R]之间的元素每次自增1,即为一个连号区间。 */ public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); //输入全排列的规模 int[] data = new int[n]; for(int i = 0;i < n;i++) //输入该全排列具体元素,易知每一个元素均布相等 data[i] = in.nextInt(); int count = 0; for(int i = 0;i < n;i++) { int max = data[i]; //从i开始到后续i~n之间每一个区间的初始最大值 int min = data[i]; //从i开始到后续i~n之间每一个区间的初始最小值 for(int j = i;j < n;j++) { if(max < data[j]) max = data[j]; if(min > data[j]) min = data[j]; if(max - min == j - i) { //此处判断就是相当于经过递增排序处理后,符合连号区间顶点 count++; } } } System.out.println(count); } }