小目标:从今天开始争取每天做一道蓝桥杯题目(用JAVA做!),希望今年能够进国赛!!!
一、矩阵相乘(去年校赛卡住的题目) 问题描述 给定一个N阶矩阵A,输出A的M次幂(M是非负整数) 例如: A = 1 2 3 4 A的2次幂 7 10 15 22 输入格式 第一行是一个正整数N、M(1<=N<=30, 0<=M<=5),表示矩阵A的阶数和要求的幂数 接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值 输出格式 输出共N行,每行N个整数,表示A的M次幂所对应的矩阵。相邻的数之间用一个空格隔开 样例输入 2 2 1 2 3 4 样例输出 7 10 15 22
思路 : 我先定义两个数组,a数组用来存放一开始的值,然后通过定义num不断地将更新的值放入后面的t数组之中,就可以减少不断的用新的数组去存旧数组的值,保证减少算法时间和空间复杂度。
代码实现 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.util.Scanner; public class Collection { public static void main(String[] args){ Scanner input=new Scanner(System.in); int n=input.nextInt(); //定义矩阵的行和列 int m=input.nextInt(); //定义矩阵乘方次数 int[][] a=new int[n][n]; //定义原始数组 for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { a[i][j] = input.nextInt(); //输入数组元素 } } int[][] t=new int[n][n]; //最终存放的数组 for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { int num=0; for(int k=0;k<n;k++) { num+=a[i][k]*a[k][j]; //利用矩阵相乘原理得到新的数组所对应的位置的值 } t[i][j]=num; //将相乘结果传给数组t } } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { System.out.print(t[i][j]+" "); } System.out.println(); //保证每行分割 } } }
代码结果如下 :
二、斐波拉契数列(基础题) 问题描述 Fn除以10007的余数是多少。 说明:在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。 样例1输入 10 样例1输出 55 样例2输入 22 样例2输出 7704 数据规模与约定 1 <= n <= 1,000,000。
思路: ①递归(不推荐) : Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.Scanner; public class Collection { public static void main(String[] args){ Scanner input=new Scanner(System.in); int n=input.nextInt(); int[] a=new int[n]; a[1]=a[2]=1; int m=feibo(n)%10007; //最终的值除以10007求余数 System.out.println(m); } public static int feibo(int n){ if(n==1||n==2) //前两个的值需要给出,才能依次算出后面的值 return 1; else return (feibo(n-1)+feibo(n-2)); //递归主要思路 } }
代码结果如下:
②动态规划 : 动态规划和递归有很大的相同处,但是动态规划而言,起码性能很高,不会出现提交代码系统超时的问题,而且很容易想到和实现。 将前两项赋值为1,然后从第三项开始是前两项加,假设算前三项,第一项为l,第二项为r,第三项为l+r。然后要计算第四项的时候,我们需要将第二项的r就成了计算第四项的l,那么第三项的sum就成了第四项计算时候的r,因此不断地替换计算,动态规划的思路就是往前推,求上一个结果的答案,然后依次推出接下来答案的结果。代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.Scanner; public class Collection { public static void main(String[] args){ Scanner input=new Scanner(System.in); int n=input.nextInt(); int[] a=new int[n]; int m=feibo(n-1,a)%10007; //题目要求对10007取余 System.out.println(m); } public static int feibo(int n,int[] a){ int l=1,r=1,sum=0; if(n<=1) return n; for(int i=2;i<=n;i++) { sum=l+r; //前两项之和 l=r; //将现在的第二项变成计算下一项的左边值 r=sum; //将现在的和变成计算下一项的右边值 } return sum; } }
代码结果如下:
三、字母图形 问题描述 利用字母可以组成一些美丽的图形,下面给出了一个例子: ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。 输入格式 输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。 输出格式 输出n行,每个m个字符,为你的图形。 样例输入 5 7 样例输出 ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 数据规模与约定 1 <= n, m <= 26。
思路: 肯定需要使用二维数组去存放最后的字母图形,使用二重循环去遍历每一个位置。通过规律可以得到只要i和j的差的绝对值为哪个数就对应字母表中和A的差距位置,因此利用数组下标 去判断绝对值为1就输出B,2就输出C,以此类推。 假设i为2,j为3: 则判断a[2][3]的位置存放的应该就是 2-3的绝对值为1所以存放B。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); int n=input.nextInt(); int m=input.nextInt(); int[][] a=new int[n][m]; char[] b={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; //用下标方便的放入相对于的值 for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { int c=i-j; //求下标之差(可能有负数) int d=(Math.abs(c))%26; //求下标之差的绝对值(如果大于26行就需要求余) System.out.print(b[d]); } System.out.println(); } } }
代码结果如下:
编程出现的问题:
定义26个字母的数组的时候写错了,导致只有百分之30的准确性。
这个题目限制了行数为26,但是如果行数太多的话下标的d就需要对26取余数(int d=(Math.abs(c))%26;)。
输出格式之间没有空格,当时打了空格,只有百分之10的准确性。
四、十进制转十六进制 问题描述 十六进制数是在程序设计时经常要使用到的一种整数的表示方式。它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。 给出一个非负整数,将它表示成十六进制的形式。 输入格式 输入包含一个非负整数a,表示要转换的数。0<=a<=2147483647 输出格式 输出这个整数的16进制表示 样例输入 30 样例输出 1E
思路: 不再像c语言那样手写,我们可以考虑直接通过使用toHexString()方法 转换成十六进制、使用toUpperCase()方法 将小写字母转换为大写字母。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); long n=input.nextLong(); //定义了一个long型的数字 System.out.printf(Long.toHexString(n).toUpperCase()); //转换为十六进制数并且为大写字母 } }
代码结果如下:
!
五、十六进制转十进制 问题描述 从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。 注:十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。 样例输入 FFFF 样例输出 65535
思路: 利用JAVA中parseLong(要被转换的数,被转换的数位几进制)方法 。 例如要将16进制的FFFF转换就需要输入n=FFFF然后调用praseLong函数(num,16)。
代码实现:
1 2 3 4 5 6 7 8 9 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); String num=input.nextLine(); Long da=Long.parseLong(num,16); System.out.println(da); } }
代码结果如下:
!
六、集合运算 问题描述 给出两个整数集合A、B,求出他们的交集、并集以及B在A中的余集。 输入格式 第一行为一个整数n,表示集合A中的元素个数。 第二行有n个互不相同的用空格隔开的整数,表示集合A中的元素。 第三行为一个整数m,表示集合B中的元素个数。 第四行有m个互不相同的用空格隔开的整数,表示集合B中的元素。 集合中的所有元素均为int范围内的整数,n、m<=1000。 输出格式 第一行按从小到大的顺序输出A、B交集中的所有元素。 第二行按从小到大的顺序输出A、B并集中的所有元素。 第三行按从小到大的顺序输出B在A中的余集中的所有元素。 样例输入 5 1 2 3 4 5 5 2 4 6 8 10 样例输出 2 4 1 2 3 4 5 6 8 10 1 3 5 样例输入 4 1 2 3 4 3 5 6 7 样例输出 1 2 3 4 5 6 7 1 2 3 4
思路: 一开始没想到集合!!想着暴力循环找到的相同的就是交集,然后A里面有的B没有的就是差集,并就是A和差集之和。 最后看大佬的思路才发现用集合 ,我选择使用Set集合
(set存放的是不重复的元素)。
add()
增加元素
retain()
求交集
remove
求差集
add两次
求并集(存放不重复的元素!)
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import java.util.HashSet; import java.util.Scanner; import java.util.Set; public class Main{ public static void main(String[] args) { Scanner input=new Scanner(System.in); Set<Integer> result=new HashSet<Integer>();//存放最终结果 Set<Integer> set1=new HashSet<Integer>();//第一个 Set<Integer> set2=new HashSet<Integer>();//第二个 int n=input.nextInt();//输入第一个集合的长度 for (int i = 0; i < n; i++) { set1.add(input.nextInt());//add输入集合的元素 } int m=input.nextInt(); //输入第二个集合的长度 for (int i = 0; i < m; i++) { set2.add(input.nextInt());//add输入集合的元素 } result.clear(); //清空结果集合 result.addAll(set1);//将第一个集合的元素放进去 result.retainAll(set2);//retain求两个的交集 System.out.println("交集 = " + result); result.clear();//清空(为下一个要求服务) result.addAll(set1);//将第一个集合的元素放进去 result.addAll(set2);//将第二个集合的元素放进去(不会把重复的放进去) System.out.println("并集 = " + result); result.clear();//清空(防止上面的过程干扰) result.addAll(set1);//将第一个集合的元素放进来 result.removeAll(set2);//将相同的元素排除掉 System.out.println("差集 = "+result); } }
代码结果如下:
因为这个题目需要让集合中的元素一个一个输出,因此需要增强for循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 result.clear(); //清空结果集合 result.addAll(set1);//将第一个集合的元素放进去 result.retainAll(set2);//retain求两个的交集 for(int i:result) System.out.print(i+" "); System.out.println(); result.clear();//清空(为下一个要求服务) result.addAll(set1);//将第一个集合的元素放进去 result.addAll(set2);//将第二个集合的元素放进去(不会把重复的放进去) for(int i:result) System.out.print(i+" "); System.out.println(); result.clear();//清空(防止上面的过程干扰) result.addAll(set1);//将第一个集合的元素放进来 result.removeAll(set2);//将相同的元素排除掉 for(int i:result) System.out.print(i+" "); System.out.println(); } }
代码结果如下:
七、报时助手 问题描述 给定当前的时间,请用英文的读法将它读出来。 时间用时h和分m表示,在英文的读法中,读一个时间的方法是: 如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“three o’clock”。 如果m不为0,则将时读出来,然后将分读出来,如5:30读作“five thirty”。 时和分的读法使用的是英文数字的读法,其中0~20读作: 0:zero, 1: one, 2:two, 3:three, 4:four, 5:five, 6:six, 7:seven, 8:eight, 9:nine, 10:ten, 11:eleven, 12:twelve, 13:thirteen, 14:fourteen, 15:fifteen, 16:sixteen, 17:seventeen, 18:eighteen, 19:nineteen, 20:twenty。 30读作thirty,40读作forty,50读作fifty。 对于大于20小于60的数字,首先读整十的数,然后再加上个位数。如31首先读30再加1的读法,读作“thirty one”。 按上面的规则21:54读作“twenty one fifty four”,9:07读作“nine seven”,0:15读作“zero fifteen”。 输入格式 输入包含两个非负整数h和m,表示时间的时和分。非零的数字前没有前导0。h小于24,m小于60。 输出格式 输出时间时刻的英文。 样例输入 0 15 样例输出 zero fifteen
思路: 分为判断分钟是否为0的情况:如果为0就直接判断小时输出“小时+o’clock”;如果不为0就要分为判断小时和分钟然后依次输出。主要是提前要用String数组分别存放好0-20 和 20 30 40 50的英文字母。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.util.Scanner; public class ReflectTest { public static void main(String[] args) { //用a和b的字符串数组存放时刻时间 String a[]={"zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty"}; String b[]={"twenty","thirty","forty","fifty"}; //设置h和m为输入的分钟和小时数 Scanner input=new Scanner(System.in); int h=input.nextInt(); int m=input.nextInt(); if(m==0)//如果分钟为0的话就是只有小时 后面加o'clock { switch(h/10)//判断输出 { case 0:System.out.println(a[h%10]+" "+"o'clock");break; //直接在a数组找 case 1:System.out.println(a[h]+" "+" "+"o'clock");break;//直接在a数组找 case 2:System.out.println(b[0]+" "+a[h%10]+" "+"o'clock");break; //twenty+个位的 } } else { switch(h/10)//和if条件里面的相同 { case 0:System.out.print(a[h%10]);break; case 1:System.out.print(a[h]);break; case 2:System.out.print(b[0]+" "+a[h%10]);break; } switch(m/10) { case 0:System.out.print(" "+a[m%10]);break; case 1:System.out.print(" "+a[m]);break;//直接在a数组找 case 2:System.out.print(" "+b[0]+" "+a[m%10]);break; case 3:System.out.print(" "+b[1]+" "+a[m%10]);break; case 4:System.out.print(" "+b[2]+" "+a[m%10]);break; case 5:System.out.print(" "+b[3]+" "+a[m%10]);break; } } } }
八、集合运算 问题描述 给出两个整数集合A、B,求出他们的交集、并集以及B在A中的余集。 输入格式 第一行为一个整数n,表示集合A中的元素个数。 第二行有n个互不相同的用空格隔开的整数,表示集合A中的元素。 第三行为一个整数m,表示集合B中的元素个数。 第四行有m个互不相同的用空格隔开的整数,表示集合B中的元素。 集合中的所有元素均为int范围内的整数,n、m<=1000。 输出格式 第一行按从小到大的顺序输出A、B交集中的所有元素。 第二行按从小到大的顺序输出A、B并集中的所有元素。 第三行按从小到大的顺序输出B在A中的余集中的所有元素。 样例输入 5 1 2 3 4 5 5 2 4 6 8 10 样例输出 2 4 1 2 3 4 5 6 8 10 1 3 5 样例输入 4 1 2 3 4 3 5 6 7 样例输出 1 2 3 4 5 6 7 1 2 3 4
解题思路: 本来打算使用数组去做,发现一排序之后相同的数字不一样在一个位置而且比较麻烦。所以我选择了用集合(TreeSet) –>交集 :使用一个tempA复制了a->然后用a移除所有b中和a相同的,然后用tempA把剩下的移除之后就剩下交集。 –>并集 :使用addALL(b)就可以吧不重复的b放进去 –>差集 :使用removeALL(b)把A和B相同的移过以外的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package lianxi; import java.util.Scanner; import java.util.TreeSet; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); TreeSet<Integer> treeSetA=new TreeSet<Integer>();//第一个集合A int n=input.nextInt(); for(int i=0;i<n;i++) { treeSetA.add(input.nextInt()); } TreeSet<Integer> treeSetB=new TreeSet<Integer>();//第二个集合B int m=input.nextInt(); for(int i=0;i<m;i++) { treeSetB.add(input.nextInt()); } input.close(); printDivide(treeSetA, treeSetB); printAdd(treeSetA, treeSetB); printRemain(treeSetA, treeSetB); } public static void printDivide(TreeSet<Integer> a,TreeSet<Integer> b) { TreeSet<Integer> tempA=(TreeSet<Integer>) a.clone();//第三个集合是复制a集合的 a.removeAll(b); tempA.removeAll(a); for (int i : tempA) { System.out.print(i + " "); } System.out.println(); } public static void printAdd(TreeSet<Integer> a,TreeSet<Integer> b) { a.addAll(b); for(int i:a) { System.out.print(i+" "); } System.out.println(); } public static void printRemain(TreeSet<Integer> a, TreeSet<Integer> b) { a.removeAll(b); for (int i : a) { System.out.print(i + " "); } System.out.println(); } }
代码结果如下:
!
九、大等于n的最小完全平方数 ** **问题描述 输出大等于n的最小的完全平方数。 若一个数能表示成某个自然数的平方的形式,则称这个数为完全平方数 Tips:注意数据范围 输入格式 一个整数n 输出格式 大等于n的最小的完全平方数 样例输入 71711 样例输出 71824 数据规模和约定 n是32位有符号整数
思路: 这道题目主要是将n先分为小于等于0和大于0的数两类,小于等于0的数最小的完全平方数就是0;而大于等于0的数需要让x转换成long型去比对。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); int n=input.nextInt(); double x=Math.sqrt(n);//取double类型的x long j=0; if(n<=0) //第一种情况结果为0 { j=0; System.out.println(j*j); } else//第二种情况结果要从x转换为long之后一个一个挪直到结果 { if((long)x*(long)x==n) j= (long)x; else j=(long)x+1; System.out.println(j*j); } } }
代码结果如下:
十、阿尔法乘积 问题描述 计算一个整数的阿尔法乘积。对于一个整数x来说,它的阿尔法乘积是这样来计算的:如果x是一个个位数,那么它的阿尔法乘积就是它本身;否则的话,x的阿尔法乘积就等于它的各位非0的数字相乘所得到的那个整数的阿尔法乘积。例如:4018224312的阿尔法乘积等于8,它是按照以下的步骤来计算的: 4018224312 → 41 82 24 31 2 → 3072 → 37 2 → 42 → 4*2 → 8 编写一个程序,输入一个正整数(该整数不会超过6,000,000),输出它的阿尔法乘积。 输入格式:输入只有一行,即一个正整数。 输出格式:输出相应的阿尔法乘积。 输入输出样例 样例输入 4018224312 样例输出 8
思路如下: 发现这个题目就是不停的乘不停的乘,一开始本来用数组但是发现两个while循环之后答案只有70%的准确率(就是因为int不能满足题意,所以改用函数+定义long型)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); long n=input.nextLong();//输入的数定义为long型 System.out.println(f(n)); } public static long f(long n) {//不断地输入n if(n<10) //满足乘积最终为个位数 return n; long sum=1; while(n>0) { if(n%10!=0) //拆开的目前位数字不为0 sum*=n%10; //不断乘积得到目前阶段的积 n/=10; //拆数(拆的更小) } return f(sum);//不停地递归找答案 } }
代码结果如下: !
十一、求阶乘最右边的第一个非0数(BigDecimal) 一个整数n的阶乘可以写成n!,它表示从1到n这n个整数的乘积。阶乘的增长速度非常快,例如,13!就已经比较大了,已经无法存放在一个整型变量中;而35!就更大了,它已经无法存放在一个浮点型变量中。因此,当n比较大时,去计算n!是非常困难的。幸运的是,在本题中,我们的任务不是去计算n!,而是去计算n!最右边的那个非0的数字是多少。例如,5!=12 34 5=120,因此5!最右边的那个非0的数字是2。再如,7!=5040,因此7!最右边的那个非0的数字是4。再如,15!= 1307674368000,因此15!最右边的那个非0的数字是8。请编写一个程序,输入一个整数n(0<n<=100),然后输出n!最右边的那个非0的数字是多少。 输入: 7 输出: 4
思路如下: 使用BigDecimal类定义一个sum得出结果用。 然后通过 valueof()
方法制造BigDecimal类的对象,通过multiply方法从1乘到n的结果返回给sum。 然后将结果通过toString()
方法转成字符串,倒序判断是不是为0最后得出结果。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.math.BigDecimal; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int n=input.nextInt(); BigDecimal sum=BigDecimal.ONE;//设置为1 for(int i=1;i<=n;i++) { sum=sum.multiply(BigDecimal.valueOf(i));//1*2*3*...*n就是一直到n(阶乘) } String s=sum.toString(); //转为字符串 for(int i=s.length()-1;i>=0;i--) { if(s.charAt(i)!='0') { System.out.println(s.charAt(i)); break ; } } } }
代码结果如下:
十二、二进制—>十进制 问题描述 编写一个程序,输入一个二进制的字符串(长度不超过32),然后计算出相应的十进制整数,并把它打印出来。 输入格式:输入为一个字符串,每个字符都是’0’或’1’,字符串的长度不超过32。 输出格式:输出一个整数。 输入输出样例 样例输入 1101 样例输出 13
思路: 方法1. 使用字符串n输入一连串2进制数字,然后通过BigInteger类对象创建BigInteger(n,2)即可得到答案。方法2. 通过字符串转字符数组,然后从最后面到最前面循环,不断地sum求和就可以了。
方法1代码实现:
1 2 3 4 5 6 7 8 9 10 import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); String n=input.next(); BigInteger s=new BigInteger(n,2);//使用new就行 System.out.println(s); } }
方法2代码实现: 注意: 1.一定要将字符1转为数字1!!! ——-(int)a[i]-48
2.pow()
用于求2的多少次方
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.*; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); String n=input.next();//输入一个字符串 int sum=0; char[] a=n.toCharArray();//字符串转成字符数组(相反就用valueOf()方法) for(int i=a.length-1;i>=0;i--)//倒序寻找(方便2的0次方增大) { sum+=((int)a[i]-48)*Math.pow(2,a.length-i-1);//一定要记得将字符1强制类型转换后减去48(0的ASCII码)*2的对应次方 } System.out.println(sum); } }
十三、阶乘末尾(求末尾len位) 问题描述 给定n和len,输出n!末尾len位。 输入格式 一行两个正整数n和len。 输出格式 一行一个字符串,表示答案。长度不足用前置零补全。 样例输入 6 5 样例输出 00720 数据规模和约定 n<=30, len<=10。
思路: 和之前的题目一样需要考虑用BigDecimal类定义一个s大数,然后调用multiply方法计算阶乘,可以直接通过输出s得到阶乘的结果。但是这个题目需要将其转换为字符串然后转换为字符数组对比长度和len大小。如果长度>len就直接输出就行,如果小于的话需要在前面输出cha这么多个0才行。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.math.BigDecimal; import java.util.*; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); int n=input.nextInt(); int len=input.nextInt(); BigDecimal s=BigDecimal.ONE;//设定一个大数s for(int i=1;i<=n;i++) { s=s.multiply(s.valueOf(i));//利用乘法方法 然后从1*2*...n } String s1=s.toString();//转成字符串s1 char[] a=s1.toCharArray();//转为字符数组a int cha=a.length-len; if(cha<0) { int jueduizhi=Math.abs(cha); while(jueduizhi--!=0) { System.out.print("0"); //差记为补几个0在前面 } for(int i=0;i<a.length;i++) { System.out.print(a[i]); //补了0之后再输出其他的数字 } } else //如果长度够长 { for (int i=cha;i<a.length;i++) { System.out.print(a[i]); //直接从cha的位置正序输出 } } } }
代码结果如下:
十四题、明明的随机数 问题描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。 输入格式 输入有2行,第1行为1个正整数,表示所生成的随机数的个数: N 第2行有N个用空格隔开的正整数,为所产生的随机数。 输出格式 输出也是2行,第1行为1个正整数M,表示不相同的随机数的个数。第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。 样例输入 10 20 40 32 67 40 20 89 300 400 15 样例输出 8 15 20 32 40 67 89 300 400
思路: 我发现动态的和数据有关的一定要去使用集合
!!!集合的动态变换比较方便!这道题目就用TreeSet集合(可以自动排序加减少重读的内容)。 然后使用while循环不断地判断是不是有下一个,用add方法去添加内容,然后添加之后size方法输出不重复的排序之后的集合长度,for循环输出每一个内容。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); while(input.hasNext()) //判断是否有下一个 { int num=input.nextInt(); TreeSet<Integer> set=new TreeSet<>(); //TreeSet集合存储 for(int i=0;i<num;i++) { set.add(input.nextInt()); //输入内容 } System.out.println(set.size()); //自动排序然后删除重复值之后的长度 for(int i:set) { System.out.print(i+" "); //增强for循环去输出结果 } } } }
代码结果如下:
十五、 黑色星期五(使用Calendar) 问题描述 有些西方人比较迷信,如果某个月的13号正好是星期五,他们就会觉得不太吉利,用古人的说法,就是“诸事不宜”。请你编写一个程序,统计出在某个特定的年份中,出现了多少次既是13号又是星期五的情形,以帮助你的迷信朋友解决难题。 输入输出样例 样例输入 1998 样例输出 3
思路: 使用JAVA中Calendar类可以很方便的得出结果,使用getInstance()方法获取一个默认时区的日历,通过set方法寻找第一个条件某个月的13号,然后通过对比Calendar类中固定的DAT_OF_WEEK==6(周五)从而满足两个条件。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int n=input.nextInt(); int sum=0;//计数 Calendar c=Calendar.getInstance();//获得一个时区默认的日历 for(int i=1;i<13;i++) { c.set(n,i,13); //寻找每个月的13号日子 if(c.get(Calendar.DAY_OF_WEEK)==6) //1是周日 2是周一 3是周二...6是周五 sum++; //如果c获得的是周五就增加一个 } System.out.println(sum); } }
代码结果如下:
十六、身份证号码升级 问题描述 从1999年10月1日开始,公民身份证号码由15位数字增至18位。(18位身份证号码简介)。升级方法为: 1、把15位身份证号码中的年份由2位(7,8位)改为四位。 2、最后添加一位验证码。验证码的计算方案: 将前 17 位分别乘以对应系数 (7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2) 并相加,然后除以 11 取余数,0-10 分别对应 1 0 x 9 8 7 6 5 4 3 2。 请编写一个程序,用户输入15位身份证号码,程序生成18位身份证号码。假设所有要升级的身份证的四位年份都是19××年 输入格式 一个15位的数字串,作为身份证号码 输出格式 一个18位的字符串,作为升级后的身份证号码 样例输入 110105491231002 样例输出 11010519491231002x 数据规模和约定 不用判断输入的15位字符串是否合理
思路: 考虑要用字符串s将15位身份证号码输入进去,然后转成字符数组a,设置一个数组b去一个一个从a拿到(赋值-48)。然后例如:49-1949我就是将4直接加190转换成194之后每一位去乘相应的系数得到最后一位,然后switch语句判断得到答案(x先用-1替换掉),最后依次输出b数组。
代码实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String s=input.next();//用字符串输入15位身份证 char[] a=s.toCharArray();//转成字符数组 int[] b=new int[16];//用16位去表示结果(17-1917只把1编程191) for(int i=0;i<a.length;i++) { b[i]=a[i];//把每一位传给int型数组b b[i]=b[i]-48;//必须减48才能从字符转为数字的0/1...9 } b[6]=b[6]+190;//将第一位x直接变成19x b[15]=(b[0]*7)+(b[1]*9)+(b[2]*10)+(b[3]*5)+(b[4]*8)+(b[5]*4)+2+9+((b[6]%10)*6)+(b[7]*3)+(b[8]*7)+(b[9]*9)+(b[10]*10)+(b[11]*5)+(b[12]*8)+(b[13]*4)+(b[14]*2);//注意我现在的只有16位(每一位对应的乘要变化) b[15]=b[15]%11;//计算出来之后对11取余 switch (b[15])//依次判断出最后一位是什么 { case 0:b[15]=1;break; case 1:b[15]=0;break; case 2:b[15]=-1;break; //先用-1代替x case 3:b[15]=9;break; case 4:b[15]=8;break; case 5:b[15]=7;break; case 6:b[15]=6;break; case 7:b[15]=5;break; case 8:b[15]=4;break; case 9:b[15]=3;break; case 10:b[15]=2;break; } for(int i=0;i<b.length;i++) { if(i!=15) System.out.print(b[i]);//输出除过最后一位的数字 else //判断最后一位 if(b[15]==-1) System.out.print("x");//这里将-1换成x else System.out.println(b[15]);//其他的就按照switch语句的答案输出 } } }
代码结果如下:
十七、不同单词个数统计(split()方法) 问题描述 编写一个程序,输入一个句子,然后统计出这个句子当中不同的单词个数。例如:对于句子“one little two little three little boys”,总共有5个不同的单词:one, little, two, three, boys。 说明:(1)由于句子当中包含有空格,所以应该用gets函数来输入这个句子;(2)输入的句子当中只包含英文字符和空格,单词之间用一个空格隔开;(3)不用考虑单词的大小写,假设输入的都是小写字符;(4)句子长度不超过100个字符。 输入格式:输入只有一行,即一个英文句子。 输出格式:输出只有一行,是一个整数,表示句子中不同单词的个数。 输入输出样例 样例输入 one little two little three little boys 样例输出 5
思路: 主要是用nextLine()输入 !!!(next会把单词之间的空格当做结束符),然后通过split()
方法 将s隔开成一个一个单词存放在String字符串数组之中,这一步其实可以输出a.length得到长度。但是这个题目必须要输出不重复单词的个数,可以通过二重循环将相同的单词其中一个变成空格 (可以二次使用split方法) 然后只要数组不为空就可以sum加一个,最终sum值就是答案。代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String s = input.nextLine();//用nextLine格式输入要判断的字符串 String[] a = s.split(" ");//用split方法得到每个单词 int sum = 0;//计数 for (int i = 0; i < a.length; i++) { for (int j = i + 1; j < a.length; j++)//二重循环依次判断 { if (a[i].equals(a[j])) { a[j] = " ";//将相同的其中一个单词换成空格 } } } for (int i = 0; i < a.length; i++) { if(a[i]!=" ") sum++;//输出不是空格的位置的单词数量 } System.out.println(sum); } }
代码结果如下:
十八、判断回文(字符串) 问题描述: 编程判断一个字符串是否是回文,当字符串是回文时,输出字符串:yes!,否则输出字符串:no!。所谓回文即正向与反向的拼写都一样,如adgda。 长度在100以内,且全为小写字母 样例输入 adgda 样例输出 yes!
思路: 我考虑的是输入字符串s1和s2对比,s1就用字符串转字符串数组的方式转成字符串数组a,然后反序得到b,从而字符串数组转字符串s2,然后进行对比。字符串—->字符串数组/字符数组:
1 2 3 String s=input.next(); char[] a=s.toCharArray();//字符数组 String[] a=s.split("");//字符串数组("里面随自己")
字符串数组—->字符串
1 2 3 4 5 6 7 String[] b=new String[n]; StringBuffer s=new StringBuffer(); for(String i:b) { s.append(i); } System.out.println(s.toString());//要用toString方法才能转成字符串
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String s1 = input.next();//输入要判断的字符串s1 String[] a = s1.split("");//利用split方法隔成字符串数组a String[] b = new String[a.length];//创建一个字符串数组b int j = 0; for (int i = a.length - 1; i >= 0; i--) { b[j++] = a[i]; //反序把a输入到b里面 } StringBuffer s2 = new StringBuffer();//使用StringBuffer 创建一个字符串s2 for (String i : b) { s2.append(i);//增强for循环将字符串数组转成字符串 } if(s1.equals(s2.toString()))//必须将s2.toString才可以判断 { System.out.println("yes!"); } else { System.out.println("no!"); } } }
代码结果如下:
十九、十六进制转10/8进制 用户输入三个字符,每个字符取值范围是0-9,A-F。然后程序会把这三个字符转化为相应的十六进制整数,并分别以十六进制,十进制,八进制输出,十六进制表示成3位,八进制表示成4位,若不够前面补0。(不考虑输入不合法的情况) 输入 1D5 输出 (注意冒号后面有一个空格) Hex: 0x1D5 Decimal: 469 Octal: 0725思路: 16进制就是直接输出;10进制就是用Long型的parseLong
方法;8进制就是使用Integer的toOctalString()
方法,但是里面的属性是Integer的valueOf方法(s,16)。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String s = input.next(); System.out.println("Hex: Ox" + s); Long shi = Long.parseLong(s, 16);//转成十进制 System.out.println("Decimal: " + shi); String ba = Integer.toOctalString(Integer.valueOf(s, 16));//转成8进制 char[] a = ba.toCharArray(); int cha = 4 - a.length; if (cha == 0) { System.out.println("Octal: " +ba); } if (cha == 1) { System.out.println("Octal: 0" +ba); } if (cha == 2) { System.out.println("Octal: 00" +ba); } if (cha == 3) { System.out.println("Octal: 000" +ba); } } }
代码结果如下:
二十、删除重复元素(使用数组下标) 问题描述 为库设计新函数DelPack,删除输入字符串中所有的重复元素。不连续的重复元素也要删除。 要求写成函数,函数内部使用指针操作。 样例输入 1223445667889 样例输出 13579 样例输入 else 样例输出 ls 数据规模和约定 字符串数组最大长度为100。
思路分析: 通过数组下标,所有的先为0而后面将字符串出现一次增加一次,当最后为1就输出(可以去掉出现两次以上的元素)
代码结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner input = new Scanner(System.in); String s=input.next(); int[] a=new int[10001]; for(int i=0;i<s.length();i++) { a[s.charAt(i)]++;//字符串的每一次为字符对应的下标数组元素从1变 } for(int i=0;i<s.length();i++) { if(a[s.charAt(i)]==1)//只让出现一次的元素输出 { System.out.print(s.charAt(i)); } } } }
代码结果如下: