zoukankan      html  css  js  c++  java
  • 第五届蓝桥杯JavaA组省赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论

    题目1、猜年龄

    题目描述
    小明带两个妹妹参加元宵灯会。别人问她们多大了,她们调皮地说:“我们俩的年龄之积是年龄之和的6倍”。小明又补充说:“她们可不是双胞胎,年龄差肯定也不超过8岁啊。”

    请你写出:小明的较小的妹妹的年龄。

    注意: 只写一个人的年龄数字,请通过浏览器提交答案。不要书写任何多余的内容。

    public class Guess_Age {
    
    
    public static void main(String[] args)
    {
    int age_small = 0;
    int age_big = 0;
    
    for(int i=1; i<100; i++)
    {
    for(int j=i+1; j<=i+8; j++)
    {
    int sum = i+j;
    int ji = i*j;
    
    if(ji == sum*6)
    {
    age_small = i;
    age_big = j;
    }
    }
    }
    System.out.println("小的妹妹的年龄:"+age_small);
    System.out.println("大的妹妹的年龄:"+age_big);
    }
    
    
    }
    
    
    题目2、李白打酒

    题目描述
    话说大诗人李白,一生好饮。幸好他从不开车。

    一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:

    无事街上走,提壶去打酒。
    逢店加一倍,遇花喝一斗。

    这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。

    请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。

    注意:通过浏览器提交答案。答案是个整数。不要书写任何多余的内容。

    public class Main {
    
      public static void main(String[] args) {
        System.out.println(f(2, 5, 9, 15));
    
      }
      public static int f(int a,int b,int c,int d){
        if (a==0 || d==0) {
          return 0 ;
        }
        if (a==1 && b==0 && c==0 && d==1) {
          return 1;
        }
        return f(a*2, b-1, c, d-1)+f(a-1, b, c-1, d-1);
      }
    }
    
    题目3、神奇算式

    题目描述
    由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。

    比如:

    210 x 6 = 1260
    8 x 473 = 3784
    27 x 81 = 2187

    都符合要求。

    如果满足乘法交换律的算式算作同一种情况,那么,包含上边已列出的3种情况,一共有多少种满足要求的算式。

    请填写该数字,通过浏览器提交答案,不要填写多余内容(例如:列出所有算式)。

    package mec.lanqiao;
     
    import java.util.*;
     
    public class Main {
    	static int cnt = 0;
     
    	// 判断一个数组里的元素是否各不相同
    	static boolean isBuTong(int[] x) {
    		Set<Integer> set = new HashSet<>();
    		for (int i = 0; i < x.length; i++) {
    			set.add(x[i]);
    		}
    		return x.length == set.size();
    	}
     
    	public static void main(String[] args) {
    		for (int n = 1000; n < 9999; n++) {
    			int[] store = { n / 1000, n / 100 % 10, n / 10 % 10, n % 10 };
    			Arrays.sort(store); // 对数组进行排序
    			if (isBuTong(store)) { // 各位数字各不相同
     
    				// 找较小乘数为1位数字的情况
    				for (int i = 0; i < store.length; i++) {
    					if (store[i] == 0) // 第一个数字为1位数,不能为0
    						continue;
    					// 判断商能否被第一个数整除,并将两个乘数的各位数字放到数组nStore中,比较nStore里的元素与store里是否完全相同
    					if (n % store[i] == 0 && n / store[i] / 100 < 10) {
    						int t = n / store[i];
    						int[] nStore = { store[i], t / 100, t / 10 % 10, t % 10 };
    						Arrays.sort(nStore);
    						boolean f = true;
    						for (int j = 0; j < 4; j++) {
    							if (store[j] != nStore[j]) {
    								f = false;
    								break;
    							}
    						}
    						if (f) {
    							cnt++; // 相同则cnt加一
    							System.out.println(store[i] + "x" + t + "=" + n);
    						}
    					}
    				}
    				// 找较小乘数为2位数字的情况
    				for (int i = 0; i < store.length; i++) {
    					if (store[i] == 0) // 第一个乘数十位数不能为0
    						continue;
    					for (int j = 0; j < store.length; j++) {
    						int first = store[i] * 10 + store[j]; // 第一个乘数
    						if (n % first == 0 && n / first / 10 < 10) {
    							int sec = n / first; // 第二个乘数
    							int[] nStore = { store[i], store[j], sec / 10,
    									sec % 10 };
    							Arrays.sort(nStore);
    							boolean f = true;
    							for (int k = 0; k < nStore.length; k++) {
    								if (store[k] != nStore[k]) {
    									f = false;
    									break;
    								}
    							}
    							if (f && first <= sec) {
    								cnt++; // 相同则cnt加一
    								System.out.println(first + "x" + sec + "=" + n);
    							}
    						}
    					}
    				}
    			}
    		}
    		System.out.println(cnt + "种");
    	}
    }
    
    题目4、写日志

    写日志是程序的常见任务。现在要求在 t1.log, t2.log, t3.log 三个文件间轮流写入日志。也就是说第一次写入t1.log,第二次写入t2.log,… 第四次仍然写入t1.log,如此反复。

    下面的代码模拟了这种轮流写入不同日志文件的逻辑。

    public class Main
    {
      private static int n = 1;
      public static void main(String args[]){
        for (int i = 0; i<=100; i++) {
          write(i,"1111");
        }
      }
    
      public static void write(int n, String msg)
      {
        n = n%3+1;   		//填空
        String filename = "t" + n + ".log";
        System.out.println("write to file: " + filename + " " + msg);
      }
    }
    
    题目5、锦标赛
    这题小编能力有限,还望大佬解决
    
    题目描述
     如果要在n个数据中挑选出第一大和第二大的数据(要求输出数据所在位置和值),使用什么方法比较的次数最少?我们可以从体育锦标赛中受到启发。
    
       如图【1.png】所示,8个选手的锦标赛,先两两捉对比拼,淘汰一半。优胜者再两两比拼...直到决出第一名。
    
       第一名输出后,只要对黄色标示的位置重新比赛即可。
    
       下面的代码实现了这个算法(假设数据中没有相同值)。
    
       代码中需要用一个数组来表示图中的树(注意,这是个满二叉树, 不足需要补齐)。它不是存储数据本身,而是存储了数据的下标。   
       
       第一个数据输出后,它所在的位置被标识为-1
    
    class A{
           //a 表示待处理的数据,长度如果不是2的次幂,则不足位置补为-1
        static void pick(int[] a)
        {
            int n = 1;
            while(n<a.length) n *= 2;
            
            
            int[] b = new int[2*n-1];
            for(int i=0; i<n; i++){ 
                if(i<a.length) 
                    b[n-1+i] = i;
                else
                    b[n-1+i] = -1;
            }
            
            //从最后一个向前处理
            for(int i=b.length-1; i>0; i-=2){
                if(b[i]<0){
                    if(b[i-1]>=0)
                        b[(i-1)/2] = b[i-1]; 
                    else
                        b[(i-1)/2] = -1;
                }
                else{
                    if(a[b[i]]>a[b[i-1]])
                        b[(i-1)/2] = b[i];
                    else
                        b[(i-1)/2] = b[i-1];
                }
            }
            
            //输出树根
            System.out.println(b[0] + ": " + a[b[0]]);
            
            //值等于根元素的位置需要重新pk
            pk(a,b,0,b[0]);
            
            //再次输出树根
            System.out.println(b[0] + ": " + a[b[0]]);
        }
    
        // a 表示待处理数据,b 二叉树,k 当前要重新比拼的位置,v 已经决胜出的值    
           static void pk(int[] a, int[] b, int k, int v)
        {
            
            int k1 = k*2+1;
            int k2 = k1 + 1;
            
            if(k1>=b.length || k2>=b.length){
                b[k] = -1;
                return;
            }
            
            if(b[k1]==v) 
                pk(a,b,k1,v);
            else
                pk(a,b,k2,v);
            
            
            //重新比较
            if(b[k1]<0){
                if(b[k2]>=0)
                    b[k] = b[k2]; 
                else
                    b[k] = -1;
                return;
            }
            
            if(b[k2]<0){
                if(b[k1]>=0)
                    b[k] = b[k1]; 
                else
                    b[k] = -1;
                return;
            }
            
            if(__________________________)  //填空
                b[k] = b[k1];
            else
                b[k] = b[k2];
        }
    }
    
    
        请仔细分析流程,填写缺失的代码。
    
        通过浏览器提交答案,只填写缺失的代码,不要填写已有代码或其它说明语句等。
    
    

    在这里插入图片描述

    题目6、六角填数

    题目描述
    如图【1.png】所示六角形中,填入1~12的数字。
    使得每条直线上的数字之和都相同。
    图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少?

    请通过浏览器提交答案,不要填写多余的内容。
    在这里插入图片描述

    public class Hex_FillNum 
    {
    // 把12个格子放入数组
    static int arr[] = new int[12];
    
    // 数组标记,0为无,1为有
    static int flag[] = new int[12];
    
    // 放存每条直线的和
    static int sum[] = new int[6];
    
    public static void main(String[] args) 
    {
    //将已知的三个数赋值, 并且将这三个数进行标记,arr[5]为所求的数
    flag[0] = 1;
    arr[0] = 1;
    flag[7] = 1;
    arr[1] = 8;
    flag[2] = 1;
    arr[11] = 3;
    fun(0);
    }
    
    public static void fun(int x)
    {
    // 这个3个数为已知,直接跳过
    if(x==0 || x==1 || x==11)
    {
    fun(x+1);
    return;
    }
    
    // 格子放满,进行判断
    if(x>11)
    {
    // 每条线上的和
    sum[0] = arr[0] + arr[2] + arr[5] + arr[7];
    sum[1] = arr[0] + arr[3] + arr[6] + arr[10];
    sum[2] = arr[7] + arr[8] + arr[9] + arr[10];
    sum[3] = arr[1] + arr[5] + arr[8] + arr[11];
    sum[4] = arr[4] + arr[6] + arr[9] + arr[11];
    sum[5] = arr[1] + arr[2] + arr[3] + arr[4];
    
    // 若每条线上的和相等
    if(sum[0]==sum[1] && sum[1]==sum[2] && sum[2]==sum[3] && sum[3]==sum[4] && sum[4]==sum[5] && sum[5] == sum[0])
    System.out.println(arr[5]);
    return;
    }
    
    // 为格子赋值
    for(int i=0; i<arr.length; i++)
    {
    if(flag[i] == 0)
    {
    flag[i] = 1;
    arr[x] = i+1;
    fun(x+1);
    flag[i] = 0;
    }
    }
    }
    }
    
    
    题目7、绳圈

    题目描述
    今有 100 根绳子,当然会有 200 个绳头。

    如果任意取绳头两两配对,把所有绳头都打结连接起来。最后会形成若干个绳圈(不考虑是否套在一起)。
    我们的问题是:请计算最后将形成多少个绳圈的概率最大?
    注意:结果是一个整数,请通过浏览器提交该数字。不要填写多余的内容。

    public class Main {
        
        public static void main(String[] args) {
            double[][] dp = new double[101][101];
            dp[1][1] = 1;  //当前只有一根绳子,只能形成一个绳圈,且概率为1
            for(int i = 2;i < 101;i++) {  //绳子数
                for(int j = 1;j < 101;j++) {  //绳圈数
                    if(j > i)  //此时的情形不可能出现,即此时概率为0
                        continue;
                    dp[i][j] = dp[i - 1][j]*(2*i - 2) / (2*i - 1) + dp[i][j -1]/(2*i - 1);
                }
            }
            double max = 0;
            int maxI = 0;
            for(int i  = 1;i < 101;i++) {
                if(max < dp[100][i]) {
                    max = dp[100][i];
                    maxI = i;
                }
            }
            System.out.println(maxI);
        }
    }
    
    题目8、兰顿蚂蚁

    标题:兰顿蚂蚁

    兰顿蚂蚁,是于1986年,由克里斯·兰顿提出来的,属于细胞自动机的一种。

    平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只“蚂蚁”。
    蚂蚁的头部朝向为:上下左右其中一方。

    蚂蚁的移动规则十分简单:
    若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;
    若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。

    规则虽然简单,蚂蚁的行为却十分复杂。刚刚开始时留下的路线都会有接近对称,像是会重复,但不论起始状态如何,蚂蚁经过漫长的混乱活动后,会开辟出一条规则的“高速公路”。

    蚂蚁的路线是很难事先预测的。

    你的任务是根据初始状态,用计算机模拟兰顿蚂蚁在第n步行走后所处的位置。

    【数据格式】

    输入数据的第一行是 m n 两个整数(3 < m, n < 100),表示正方形格子的行数和列数。
    接下来是 m 行数据。
    每行数据为 n 个被空格分开的数字。0 表示白格,1 表示黑格。

    接下来是一行数据:x y s k, 其中x y为整数,表示蚂蚁所在行号和列号(行号从上到下增长,列号从左到右增长,都是从0开始编号)。s 是一个大写字母,表示蚂蚁头的朝向,我们约定:上下左右分别用:UDLR表示。k 表示蚂蚁走的步数。

    输出数据为两个空格分开的整数 p q, 分别表示蚂蚁在k步后,所处格子的行号和列号。

    例如, 输入:
    6
    0 0 0 0 0
    0 0 0 0 0
    0 1 0 0 0
    0 0 0 0 0
    0 0 0 0 0
    3 L 5
    程序应该输出:
    3

    再例如, 输入:
    3
    0 0
    1 1
    1 1
    1 U 6
    程序应该输出:
    0

    资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗 < 1000ms

    请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

    所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
    注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
    注意:主类的名字必须是:Main,否则按无效代码处理。

    import java.util.Scanner;
    
    public class Main {
        public static int[][] move = {{-1,0},{1,0},{0,-1},{0,1}};//表示分别向上、下、左、右移动一步
        public static int[] left = {2,1,3,0}; //向左转90度,其中2向左、1向下、3向右、0向上
        public static int[] right = {2,0,3,1}; //向右转90度,具体数字含义同上
        
        public void bfs(int[][] value, int x, int y, String tempArea, int count) {
            int area = 0;
            if(tempArea.equals("L"))
                area = 2;
            else if(tempArea.equals("R"))
                area = 3;
            else if(tempArea.equals("U"))
                area = 0;
            else if(tempArea.equals("D"))
                area = 1;
            int step = 0;
            while(step < count) {
                if(value[x][y] == 1) {  //黑色格子,当前方向area要向右转90度
                    value[x][y] = 0;
                    int i = 0;
                    for(;i < 4;i++) {
                        if(right[i] == area)
                            break;
                    }
                    i = (i + 1) % 4;
                    area = right[i];
                    x = x + move[area][0];
                    y = y + move[area][1];        
                    step++;
                } else {   //白色格子,当前方向area要向左转90度
                    value[x][y] = 1;
                    int i = 0;
                    for(;i < 4;i++) {
                        if(left[i] == area)
                            break;
                    }
                    i = (i + 1) % 4;
                    area = left[i];
                    x = x + move[area][0];
                    y = y + move[area][1];
                    step++;
                }
            }
            System.out.println(x+" "+y);
            return;
        }
        
        public static void main(String[] args) {
            Main test = new Main();
            Scanner in = new Scanner(System.in);
            int m = in.nextInt();
            int n = in.nextInt();
            int[][] value = new int[m][n];
            for(int i = 0;i < m;i++)
                for(int j = 0;j < n;j++)
                    value[i][j] = in.nextInt();
            int x = in.nextInt();
            int y = in.nextInt();
            String tempArea = in.next();
            int count  = in.nextInt();
            test.bfs(value, x, y, tempArea, count);
        }
    }
    
    题目9、斐波那契

    标题:斐波那契

    斐波那契数列大家都非常熟悉。它的定义是:
    
    f(x) = 1                    .... (x=1,2)
    f(x) = f(x-1) + f(x-2)      .... (x>2)
    
    对于给定的整数 n 和 m,我们希望求出:
    f(1) + f(2) + ... + f(n)  的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
    公式参见【图1.png】
    
    但这个数字依然很大,所以需要再对 p 求模。
    

    【数据格式】
    输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)
    输出为1个整数

    例如,如果输入:
    3 5
    程序应该输出:

    再例如,输入:
    11 29
    程序应该输出:

    资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗 < 2000ms

    请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

    所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
    注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
    注意:主类的名字必须是:Main,否则按无效代码处理。

    首先,关于斐波那契数的求取,如果使用递归法求取,会出现远远超时;迭代法求取差不多也会超时,此处,最好使用矩阵相乘法求取第n个斐波那契数。

    其次,关于求取前n个斐波那契数和的问题,利用斐波那契数的性质(网上资料参考所得):S(n) = F(n+2) - 1,其中S(n)是前n个斐波那契数的和,F(n + 2)是第n+2个斐波那契数。

    最后,要考虑n,m的取值问题,经过使用计算机运算检测,一般n > 100,F(n)就会超过long型最大值,所以此处建议使用BigInteger类型,来存储斐波那契数。

    下面的代码仅供参考,不保证n、m、p达到10^18数量级时,大整数类型的取余不会出现内存溢出问题哦。

    import java.math.BigInteger;
    import java.util.Scanner;
    
    public class Main {
        public static BigInteger[][] ONE = {{BigInteger.ONE, BigInteger.ONE},
            {BigInteger.ONE,BigInteger.ZERO}};
        public static BigInteger[][] ZERO = {{BigInteger.ZERO,BigInteger.ZERO},
            {BigInteger.ZERO,BigInteger.ZERO}};
        //求取矩阵ONE的n次方
        public BigInteger[][] getOneOfN(long n) {
            if(n == 0)
                return ZERO;
            if(n == 1)
                return ONE;
            if((n & 1) == 0) {   //当n为偶数时
                BigInteger[][] A = getOneOfN(n >> 1);
                return multiMatrix(A, A);
            }
            //当n为奇数时
            BigInteger[][] A = getOneOfN(n >> 1);
            return multiMatrix(multiMatrix(A, A), ONE);
        }
        //求取矩阵A*B的值
        public BigInteger[][] multiMatrix(BigInteger[][] A, BigInteger[][] B) {
            BigInteger[][] result = new BigInteger[A.length][B[0].length];
            for(int i = 0;i < A.length;i++)
                for(int j = 0;j < B[0].length;j++)
                    result[i][j] = BigInteger.ZERO;
            for(int i = 0;i < A.length;i++)
                for(int j = 0;j < B.length;j++)
                    for(int k = 0;k < A[0].length;k++)
                        result[i][j] = result[i][j].add(A[i][k].multiply(B[k][j]));
            return result;
        }
        //获取第n个斐波那契数
        public BigInteger getFibonacci(long n) {
            if(n == 1 || n == 2)
                return BigInteger.ONE;
            BigInteger[][] A  = new BigInteger[1][2];
            A[0][0] = BigInteger.ONE;
            A[0][1] = BigInteger.ONE;
            BigInteger[][] B = getOneOfN(n - 2);
            A = multiMatrix(A, B);
            return A[0][0];
        }
        
        public static void main(String[] args) {
            Main test = new Main();
            Scanner in = new Scanner(System.in);
            long n = in.nextLong();
            long m = in.nextLong();
            BigInteger p = in.nextBigInteger();
            BigInteger result = BigInteger.ZERO;
            result = test.getFibonacci(n + 2).subtract(BigInteger.ONE);
            result = result.mod(test.getFibonacci(m));
            result = result.mod(p);
            System.out.println(result);
        }
        
    }
    
    题目10、波动数列

    标题:波动数列

    观察这个数列:
    

    3 0 2 -1 1 -2 …

    这个数列中后一项总是比前一项增加2或者减少3。
    
    栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢?
    

    【数据格式】
    输入的第一行包含四个整数 n s a b,含义如前面说述。
    输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数。

    例如,输入:
    10 2 3
    程序应该输出:

    【样例说明】
    这两个数列分别是2 4 1 3和7 4 1 -2。

    【数据规模与约定】
    对于10%的数据,1<=n<=5,0<=s<=5,1<=a,b<=5;
    对于30%的数据,1<=n<=30,0<=s<=30,1<=a,b<=30;
    对于50%的数据,1<=n<=50,0<=s<=50,1<=a,b<=50;
    对于70%的数据,1<=n<=100,0<=s<=500,1<=a, b<=50;
    对于100%的数据,1<=n<=1000,-1,000,000,000<=s<=1,000,000,000,1<=a, b<=1,000,000。

    资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗 < 2000ms

    请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

    所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
    注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
    注意:主类的名字必须是:Main,否则按无效代码处理。

    import java.util.Scanner;
    
    public class Main {
        public static int count = 0;
        public static int n = 0;
        public static int s = 0;
        public static int a = 0;
        public static int b = 0;
        public static int sum = 0;
        
        public void dfs(int i, int step) {
            if(step == n) {
                if(sum == s)
                    count = (count + 1) % 100000007;
                return;
            }
            sum += i;
            dfs(i + a, step + 1);
            dfs(i - b, step + 1);
            sum -= i;
            return;
        }
        
        public static void main(String[] args) {
            Main test = new Main();
            Scanner in = new Scanner(System.in);
            n = in.nextInt();
            s = in.nextInt();
            a = in.nextInt();
            b = in.nextInt();
            for(int i=s-n*b;i<s+n*a;i++)
                test.dfs(i, 1);
            System.out.println(count);
        }
    }
    
  • 相关阅读:
    工具类---xlsx文件读写
    2021上半年第二次作业总结
    2021上半年第一次作业总结
    C语言II博客作业04
    C语言II—作业03
    C语言II博客作业02
    C语言II博客作业01
    win7开启snmp服务实现监控过程展现
    台湾某医学会sql注入漏洞
    测试面试题(持续总结中)
  • 原文地址:https://www.cnblogs.com/a1439775520/p/13078097.html
Copyright © 2011-2022 走看看