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);
        }
    }
    
  • 相关阅读:
    微信小程序HTTPS
    微信商城-1简介
    va_list
    Event log c++ sample.
    EVENT LOGGING
    Analyze Program Runtime Stack
    unknow table alarmtemp error when drop database (mysql)
    This application has request the Runtime to terminate it in an unusual way.
    How to check if Visual Studio 2005 SP1 is installed
    SetUnhandledExceptionFilter
  • 原文地址:https://www.cnblogs.com/a1439775520/p/13078096.html
Copyright © 2011-2022 走看看