• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
百事可爱
一起努力鸭~~~
博客园    首页    新随笔    联系   管理    订阅  订阅
蓝桥2013年C组练习

蓝桥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   */
posted on 2022-03-26 10:07  精致猪猪侠  阅读(87)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3