蓝桥2013年C组练习
第一题:猜年龄
题目描述:
美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。 一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说:
“我年龄的立方是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。
请你推算一下,他当时到底有多年轻。
通过浏览器,直接提交他那时的年龄数字。
注意:不要提交解答过程,或其它的说明文字。
package 蓝桥C组练习;
import java.util.HashSet;
import java.util.Set;
//分析:
//从11岁开始判断,年龄满足三个条件:
/*年龄的立方是个4位数 ,年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。
* 1. 用到字符串的拼接
* 2. 年龄的位数用字符串的 String.length()方法判断
* 3. 对于每个数字只允许出现一次,借助Set接口:集合元素不可重复; 元素个数用size()方法
* 4. String.charAt(下标) 取出字符串的每一个字符
* 5. 不创建对象时,将变量和方法直接在本类中设为 static ,全局的静态变量和方法,这样才可以直接在main 方法中直接调用*/
public class Cai {
//泛型用引用类型,char所对应的包装类型是Character
static Set<Character> set = new HashSet<>();
public static void main(String[] args) {
for(int age=11;age<50;age++) {
String age3 = age*age*age+"";
String age4 = age*age*age*age+"";//此处,拼接空字符串 实现int 转为 String
//三个条件判断
if(age3.length() == 4 && age4.length()==6 && check(age3, age4)) {
System.out.println(age);
break; //非常重要
}
}
}
//判断第三个条件:这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次
public static boolean check(String age3,String age4) {
String string = age3 + age4;//字符串的拼接
//对字符串遍历,依次添加到Set集合中,会自动过滤重复的数字,最后判断集合大小,若是10,则满足条件
for (int i = 0; i < string.length(); i++) {
set.add(string.charAt(i));
}
return set.size()==10;
}
}
//18
第二题:组素数:
题目描述:
素数就是不能再进行等分的数。比如:2 3 5 7 11 等。
9 = 3 * 3 说明它可以3等分,因而不是素数。
我们国家在1949年建国。如果只给你 1 9 4 9 这4个数字卡片,可以随意摆放它们的先后顺序(但卡片不能倒着摆放啊,我们不是在脑筋急转弯!),那么,你能组成多少个4位的素数呢?比如:1949,4919 都符合要求。
请你提交:能组成的4位素数的个数,不要罗列这些素数!!
注意:不要提交解答过程,或其它的辅助说明文字。
1. 循环嵌套
package 蓝桥C组练习;
import java.util.HashSet;
import java.util.Set;
/*分析:
* 对1 9 4 9 这4个数字进行全排列,然后找到其中是素数的个数
* 1. 全排列方法有两种,一是循环嵌套,二是递归
* 2. 素数(质数)从2开始查询,若一个数一直除以到它的开方,若都除不尽,后面的数字一定除不进,即此数为素数
* 3. int型的包装类型是Integer*/
public class SuShu {
static Set<Integer> set = new HashSet<>();
public static void main(String[] args) {
int[] arr = {1,9,4,9};
//循环嵌套
for (int a = 0; a < arr.length; a++) {//a,b,c,d代表数组的下标
for (int b = 0; b < arr.length; b++) {
if(b==a) continue;
for (int c = 0; c < arr.length; c++) {
if(c==a||c==b) continue;
for (int d = 0; d < arr.length; d++) {
if(d==a||d==b||d==c) continue;
int num = arr[a]*1000+arr[b]*100+arr[c]*10+arr[d];
//判断素数
boolean r = true;//标记位
for(int i=2;i<=Math.sqrt(num);i++) {
if(num%i==0) {//除尽
r = false;
break;
}
}
if(r==true) {//是素数
//因为有两个9,就会出现重复的数字,要利用Set集合的不可重复,将所有素数放进集合中,自动过滤掉重复的数字
set.add(num);//自动装箱
}
}
}
}
}
System.out.println(set.size());
//也可以看是那些数字
System.out.println(set.toString());
}
/*6
[9491, 9941, 4919, 1499, 9419, 1949]
*/
}
2. 交换法全排列
package 蓝桥C组练习;
import java.util.HashSet;
import java.util.Set;
//交换法实现全排列
public class SuShu2 {
static Set<Integer> set = new HashSet<>();
public static void main(String[] args) {
int[] arr = {1,9,4,9};
sort(arr, 0, arr.length-1);
System.out.println(set.size());
}
public static void sort(int[] arr,int start,int end) {
//出口
if(start == end) {//全排列的某一种方案
int num = arr[0]*1000+arr[1]*100+arr[2]*10+arr[3];
//判断素数
boolean r = true;//标记位
for(int i=2;i<=Math.sqrt(num);i++) {
if(num%i==0) {//除尽
r = false;
break;
}
}
if(r==true) {//是素数
//因为有两个9,就会出现重复的数字,要利用Set集合的不可重复,将所有素数放进集合中,自动过滤掉重复的数字
set.add(num);//自动装箱
}
}
for(int i = start; i <= end; i++) {
swap(arr, start, i);
sort(arr, start+1, end);
swap(arr, start, i);
}
}
//交换数组元素
public static void swap(int[] arr,int i,int j) {
int c = arr[i];
arr[i] = arr[j];
arr[j] = c;
}
}
交换法固定模板 (1) (当给定的数据范围个数和取得全排列的个数相等)
//交换法实现全排列
public class Test {
public static void main(String[] args) {
int[] arr = {1,2,3};
sort(arr, 0, arr.length-1);
}
/**
* @param arr 存放着要全排列的数字
* @param start 排序交换时定住的首位下标
* @param end 排序交换时末尾元素的下标
*/
public static void sort(int[] arr,int start,int end) {
//出口
if(start == end) {//全排列的某一种方案
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
for(int i = start; i <= end; i++) {
swap(arr, start, i);
sort(arr, start+1, end);
swap(arr, start, i);
}
}
//1[23] 12[3] 123 回溯到13[2] 132 还原为123
//2[13] 21[[3] 213 回溯到23[1] 231 还原为123
//3[12] 31[2] 312 回溯到32[1] 321
//交换数组元素
public static void swap(int[] arr,int i,int j) {
int c = arr[i];
arr[i] = arr[j];
arr[j] = c;
}
/*
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2
*/
}
(2)实现从m个数字里面取n个数字进行全排列(此时,m个数字不重复)
public class T3 {
//要实现从5个不重复的数字中取出3个进行全排列
static int count = 0;//统计种数
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int n = 3;//要取的数字个数
List<Integer> list = new ArrayList<>();//List集合:有下标,可重复
//使用List集合保存每次取出的三个数字,但不是直接add添加,先将集合的长度进行固定,要通过添加元素的方式固定 (添加的元素只要不和要排列的数字相同即可)
for (int i = 0; i <n; i++) {
list.add(-1);
}//实现集合的长度固定为3
sortAll(list,arr,n);
System.out.println(count);
}
public static void sortAll(List<Integer> list,int[] arr,int n) {
//出口
if(n==0) {//取出其中一种三位数排列组合
System.out.println(list);
count++;
return;
}
for (int i = 0; i < arr.length; i++) {
if(!list.contains(arr[i])) {//将数组中的元素依次取出,若集合中不包含此元素,就添加到集合中 !false = true
list.set(list.size()-n,arr[i]);//set(下标,元素) 若n=3, 则list.size()-n=3-3=0 list.size()已经固定了
}
else {
continue;
}
sortAll(list, arr,n-1);//更新n
list.set(list.size()-n,-1);//还原 特别注意:原来集合中只有三位-1
}
}
/*
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 3, 2]
[1, 3, 4]
[1, 3, 5]
[1, 4, 2]
[1, 4, 3]
[1, 4, 5]
[1, 5, 2]
[1, 5, 3]
[1, 5, 4]
[2, 1, 3]
[2, 1, 4] 。。。。。
省略一部分结果展示
60
*/
}
(3)实现从m个数字里面取n个数字进行全排列(此时,m个数字有重复)
package 全排列模板01;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
//实现从m个数字里面取n个数字进行全排列(此时,m个数字有重复)
// 按照上一套模板,得不到例如 122这样的数字
/*则在List集合中不存储具体数据,而是存储下标,这样得到全排列的下标,然后根据下标得到全排列的数字
* 因为m个数字有重复,所以排列组合中也会有重复数据,可以使用Set进行存储
先实现带有位数上有重复数字的全排列,再去重!!!!*/
import java.util.Set;
public class T3 {
static Set<String> set = new HashSet<>();
public static void main(String[] args) {
int[] arr = { 1, 2, 2, 4, 5 };
int n = 3;// 要取的数字个数
List<Integer> list = new ArrayList<>();// List集合:有下标,可重复
// 使用List集合保存每次取出的三个数字,但不是直接add添加,先将集合的长度进行固定,要通过添加元素的方式固定
for (int i = 0; i < n; i++) {
list.add(-1);
} // 实现集合的长度固定为n
sortAll(list, arr, n);
System.out.println(set.size());
System.out.println(set);
}
public static void sortAll(List<Integer> list, int[] arr, int n) {
// 出口
if (n == 0) {// 取出其中一种三位下标排列组合
//根据下标,得到对应的数据
String string = arr[ list.get(0) ]+""+arr[list.get(1)]+""+arr[list.get(2)];
//为了过滤重复数据
set.add(string);
// count++; 因为它包含了重复数据
return;
}
for (int i = 0; i < arr.length; i++) {
if (!list.contains(i)) {// 将数组中的下标依次取出,若集合中不包含此下标,就添加到集合中
list.set(list.size() - n,i);// set(下标,元素) 若n=3, 则list.size()-n=3-3=0
} else {
continue;
}
sortAll(list, arr, n - 1);// 更新n
list.set(list.size() - n, -1);// 还原 特别注意:原来集合中只有三位-1
}
}
/*输出结果:
33
[152, 251, 252, 154, 451, 254,。。。。。。。
*/
}
3.第三题:马虎的算式
题目描述:
假设 a b c d e 代表1~9不同的5个数字(注意是各不相同的数字,且不含0)
能满足形如: ab * cde = adb * ce 这样的算式一共有多少种呢?
请你利用计算机的优势寻找所有的可能,并回答不同算式的种类数。
满足乘法交换律的算式计为不同的种类,所以答案肯定是个偶数。
答案直接通过浏览器提交。
注意:只提交一个表示最终统计种类数的数字,不要提交解答过程或其它多余的内容。
循环嵌套
public class T3 {
public static void main(String[] args) {
//循环嵌套:
int count = 0;// 满足条件的式子个数
for (int a = 1; a <= 9; a++) {
for (int b = 1; b <= 9; b++) {
if (b == a)
continue;// 各不相同的数字,且不含0
for (int c = 1; c <= 9; c++) {
if (c == a || c == b)
continue;
for (int d = 1; d <= 9; d++) {
if (d == a || d == b || d == c)
continue;
for (int e = 1; e <= 9; e++) {
if (e == a || e == b || e == c || e == d)
continue;
if ((a * 10 + b) * (c * 100 + d * 10 + e) == (a * 100 + d * 10 + b) * (c * 10 + e))
count++;
}
}
}
}
}
System.out.println(count);// 142
}
递归
package 蓝桥C组练习;
import java.util.ArrayList;
import java.util.List;
// 实现从m个数字里面取n个数字进行全排列 (此时,m个数字不重复)
public class T3 {
static int count = 0;//统计种数
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
int n=5;//要取的数字个数
List<Integer> list = new ArrayList<>();//List集合:有下标,可重复
//使用List集合保存每次取出的五个数字,但不是直接add添加,先将集合的长度进行固定,要通过添加元素的方式固定
for (int i = 0; i <n; i++) {
list.add(-1);
}//实现集合的长度固定
sortAll(list, arr,n);
System.out.println(count);
}
public static void sortAll(List<Integer> list,int[] arr,int n) {
//出口
if(n==0) {//取出其中一种排列组合
//将此排列组合各个数取出
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);
if ((a * 10 + b) * (c * 100 + d * 10 + e) == (a * 100 + d * 10 + b) * (c * 10 + e))
count++;
return;
}
for (int i = 0; i < arr.length; i++) {
if(!list.contains(arr[i])) {//将数组中的元素依次取出,若集合中不包含此元素,就添加到集合中
list.set(list.size()-n,arr[i]);//set(下标,元素)
}
else {
continue;
}
sortAll(list, arr,n-1);//更新n
list.set(list.size()-n,-1);//还原 特别注意:原来集合中所有n位是-1
}
}
//142
}
第四题:第39级台阶
题目描述
小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
请你利用计算机的优势,帮助小明寻找答案。
要求提交的是一个整数。
注意:不要提交解答过程,或其它的辅助说明文字。
当台阶数较小时推理:
//若一次跨一阶或两阶,共走三步:
public class T4 {
static int count = 0;//统计走法
static int[] arr = new int[3];//数组记录每一次走法,每个元素记录一步跨的台阶数 112 就是第一步迈了一个台阶 ,第 二 步迈了一个台阶
public static void main(String[] args) {
walk(0,0);
System.out.println(count);
}
/**
* @param step 跨过的台阶数
* @param walkCount 走路的步数
*/
public static void walk(int step,int walkCount) {
//出口
if(walkCount>=3) {
count++;
System.out.println(arr[0]+""+arr[1]+""+arr[2]);
return;
}
arr[walkCount]=1;
walk(step+1,walkCount+1); //跨一阶,步数加1
arr[walkCount]=2;
walk(step+2,walkCount+1); //跨两阶,步数加1
}
/*
111
112
121
122
211
212
221
222
8
*/
}
/*分析:
* 首先:
* 第一层:(0,0)传进来,arr[0]=1,递归调用walk(0+1,0+1)
* 第二层:(1,1)传进来,递归调用walk(1+1,1+1)
* 第三层:(2,2)传进来,递归调用walk(2+1,2+1)
* if(walkCount>=3), 执行return 此处是第一种走法 1,1,1
* 回溯到第三层:(2,2)传进来,递归调用walk(2+2,2+1)
* 执行return 此处是第二种走法 1,1,2
* 回溯到第二层:(1,1)传进来,递归调用walk(1+2,1+1)
* 第三层:(3,2)传进来,递归调用walk(3+1,2+1)
* 执行return 此处是第三种走法 1,2,1
* 共8种*/
此题解法:
package 蓝桥C组练习;
//每一步只能迈上1个或2个台阶 一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
public class T4 {
static int count = 0;
public static void main(String[] args) {
walk(0,0);
System.out.println(count);
}
/**
* @param step 跨过的台阶数
* @param walkCount 走路的步数
*/
public static void walk(int step,int walkCount) {
//出口
if(step>39) {
return;
}
if(step == 39 && walkCount%2==0) {
count++;
return;
}
walk(step+1,walkCount+1); //跨一阶,步数加1
walk(step+2,walkCount+1); //跨两阶,步数加1
}
/*
51167078
*/
}
第五题:有理数类
题目描述:
有理数就是可以表示为两个整数的比值的数字。一般情况下,我们用近似的小数表示。但有些时候,不允许出现误差,必须用两个整数来表示一个有理数。 这时,我们可以建立一个“有理数类”,下面的代码初步实现了这个目标。为了简明,它只提供了加法和乘法运算。
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);
请分析代码逻辑,并推测划线处的代码,通过网页提交
注意:仅把缺少的代码作为答案,千万不要填写多余的代码、符号或说明文字!
package 蓝桥C组练习;
/*分析:
* 首先分析所给代码,就是方法的功能
* */
class Rational
{
//一个数有分子和分母
private long ra;
private long rb;
//2.分析gcd方法:可以自己测试其功能: ( 实现了求最大公约数的函数模板 )
private long gcd(long a, long b){
if(b==0) return a;
return gcd(b,a%b);
}
/*6,9
*9,6%9=6
*6,9%6=3
*3, 6%3=0
*b==0 a=3*/
//构造方法 (将分子和分母进行约分)
public Rational(long a, long b){
ra = a;
rb = b;
long k = gcd(ra,rb);
if(k>1){ //需要约分
ra /= k; // ra = ra/k
rb /= k;
}
}
// 加法
public Rational add(Rational x){
return new Rational( ra*x.rb + rb*x.ra, rb*x.rb) ; //填空位置
}
// 乘法
public Rational mul(Rational x){
return new Rational(ra*x.ra, rb*x.rb);
}
//重写toString
public String toString(){
if(rb==1) return "" + ra;
return ra + "/" + rb;//得到:1. ra是分子,rb是分母
}
}
//测试乘法:
public static void main(String[] args) {
Rational a = new Rational(1, 3);//a.ra=1 a.rb=3
Rational b = new Rational(1, 6);//b.ra=1 b.rb=6
Rational c = a.mul(b);
System.out.println(a + "*" + b + "=" + c);
}
// // 乘法
// public Rational mul(Rational x){
// return new Rational(ra*x.ra, rb*x.rb);
// }
//分析:Rational c = a.mul(b);
// public Rational mul(Rational b){
// return new Rational(a.ra*b.ra, a.rb*b.rb);
// } 就是分子*分子 分母*分母 return new Rational(1*1,3*6);
//1/3*1/6=1/18
/测试加法:
public static void main(String[] args) {
Rational a = new Rational(1, 3);//a.ra=1 a.rb=3
Rational b = new Rational(1, 6);//b.ra=1 b.rb=6
Rational c = a.add(b);
System.out.println(a + "+" + b + "=" + c);
//1/3+1/6=1/2
}
/* 1/3 + 1/6 = 6/18 + 3/18 = 9/18 = 1/2
* 构造方法Rational,可以实现约分 9/18 = 1/2
* 关键得到9/18, 1*6+1*3=9 3*6=18
* 分子: a.ra*b.rb + a.rb*b.ra
* 分母: a.rb*b.rb */
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现