第七届蓝桥杯JavaA组国(决)赛部分真题

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

题目1、阶乘位数

阶乘位数

9的阶乘等于:362880
它的二进制表示为:1011000100110000000
这个数字共有19位。

请你计算,9999 的阶乘的二进制表示一共有多少位?

注意:需要提交的是一个整数,不要填写任何无关内容(比如说明解释等)

答案:118445

import java.math.BigInteger;

public class Main {
    
    public static void main(String[] args) {
        BigInteger result = new BigInteger("1");
        for(int i = 1;i <= 9999;i++) {
            BigInteger temp = new BigInteger(""+i);
            result = result.multiply(temp);
        }
        long count = 0;
        BigInteger a = new BigInteger("2");
        while(result.compareTo(BigInteger.ZERO) > 0) {
            count++;
            result = result.divide(a);
            //System.out.println("count = "+count);
        }
        System.out.println(count);
    }
}
题目2、凑平方数

把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721

再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等…

注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。

如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?

注意:需要提交的是一个整数,不要填写多余内容。

答案:300

import java.util.Arrays;
import java.util.HashSet;

public class Main {
    public static HashSet<String> set = new HashSet<String>();
    
    public void swap(int[] A, int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
    
    public void dfsAllSort(int[] A, int step) {
        if(step == A.length) {
            long[] B = new long[A.length];
            dfsSqrtNum(A, 0, B, 0);
            return;
        } else {
            for(int i = step;i < A.length;i++) {
                swap(A, i, step);
                dfsAllSort(A, step + 1);
                swap(A, i, step);
            }
        }
    }
    
    public void dfsSqrtNum(int[] A, int step, long[] B, int num) {
        if(step == A.length) {
            StringBuffer s = new StringBuffer("");
            long[] arrayA = new long[num];
            for(int i = 0;i < num;i++)
                arrayA[i] = B[i];
            Arrays.sort(arrayA);
            for(int i = 0;i < num;i++) {
                s.append(arrayA[i]);
                if(i != num - 1)
                    s.append("-");
            }
            set.add(s.toString());
            return;
        }
        
        if(A[step] == 0) {
            B[num] = 0;
            dfsSqrtNum(A, step + 1, B, num + 1);
        } else {
            long sum = 0;
            for(int i = step;i < A.length;i++) {
                sum = sum * 10 + A[i];
                double son = Math.sqrt(sum * 1.0);
                long a = (long) son;
                if(a == son) {
                    B[num] = sum;
                    dfsSqrtNum(A, i + 1, B, num + 1);
                }
            }
        }
        
    }
    
    public static void main(String[] args) {
        Main test = new Main();
        int[] A = {0,1,2,3,4,5,6,7,8,9};
        test.dfsAllSort(A, 0);
        System.out.println(set.size());
    }
}
题目3、棋子换位
棋子换位

有n个棋子A,n个棋子B,在棋盘上排成一行。
它们中间隔着一个空位,用“.”表示,比如:

AAA.BBB

现在需要所有的A棋子和B棋子交换位置。
移动棋子的规则是:
1. A棋子只能往右边移动,B棋子只能往左边移动。
2. 每个棋子可以移动到相邻的空位。
3. 每个棋子可以跳过相异的一个棋子落入空位(A跳过B或者B跳过A)。

AAA.BBB 可以走法:
移动A ==> AA.ABBB
移动B ==> AAAB.BB

跳走的例子:
AA.ABBB ==> AABA.BB

以下的程序完成了AB换位的功能,请仔细阅读分析源码,填写划线部分缺失的内容。



public class Main
{
    static void move(char[] data, int from, int to)
    {
        data[to] = data[from];
        data[from] = '.';
    }
    
    static boolean valid(char[] data, int k)
    {
        if(k<0 || k>=data.length) return false;
        return true;
    }
    
    static void f(char[] data)
    {
        while(true){
            boolean tag = false;
            for(int i=0; i<data.length; i++){
                int dd = 0; // 移动方向
                if(data[i]=='.') continue;
                if(data[i]=='A') dd = 1;
                if(data[i]=='B') dd = -1;
                
                if(valid(data, i+dd) && valid(data,i+dd+dd) 
                && data[i+dd]!=data[i] && data[i+dd+dd]=='.'){ 
                // 如果能跳...
                    move(data, i, i+dd+dd);
                    System.out.println(new String(data));
                    tag = true;
                    break;
                }
            }
            
            if(tag) continue;
            
            for(int i=0; i<data.length; i++){
                int dd = 0; // `移动方向
                if(data[i]=='.') continue;
                if(data[i]=='A') dd = 1;
                if(data[i]=='B') dd = -1;            
                     
                if(valid(data, i+dd) && data[i+dd]=='.'){ 
                // 如果能移动...
                    if( _____________________ ) continue;  //填空位置
                    move(data, i, i+dd);
                    System.out.println(new String(data));
                    tag = true;
                    break;
                }
            }
            
            if(tag==false) break;                    
        }
    }
    
    public static void main(String[] args)
    {
        char[] data = "AAA.BBB".toCharArray();    
        f(data);
    }
}



注意:只提交划线部分缺少的代码,不要复制已有代码或填写任何多余内容。



答案:valid(data,i+dd+dd) && valid(data, i-dd) && data[i-dd] == data[i+dd+dd]
题目4、机器人塔

X星球的机器人表演拉拉队有两种服装,A和B。
他们这次表演的是搭机器人塔。

类似:

     A
    B B
   A B A
  A A B B
 B B B A B
A B A B B A

队内的组塔规则是:

A 只能站在 AA 或 BB 的肩上。
B 只能站在 AB 或 BA 的肩上。

你的任务是帮助拉拉队计算一下,在给定A与B的人数时,可以组成多少种花样的塔。

输入一行两个整数 M 和 N,空格分开(0<M,N<500),分别表示A、B的人数,保证人数合理性。

要求输出一个整数,表示可以产生的花样种数。

例如:
用户输入:
1 2

程序应该输出:
3

再例如:
用户输入:
3 3

程序应该输出:
4

资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms

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

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

import java.util.Scanner;

public class Main {
    public static int m, n;
    public static int[][] value;   //此处用数字1代表A,数字2代表B
    public static int len, count = 0;
    
    public void check() {
        for(int i = len - 2, t = 1;i >= 0;i--, t++)
            for(int j = 0;j < len - t;j++) {
                if(value[i + 1][j] == value[i + 1][j + 1])
                    value[i][j] = 1;
                else
                    value[i][j] = 2;
            }
        int sumA = 0, sumB = 0;
        for(int i = 0, t = len - 1;i < len;i++, t--)
            for(int j = 0;j < len - t;j++) {
                if(value[i][j] == 1)
                    sumA++;
                else if(value[i][j] == 2)
                    sumB++;
            }
        if(sumA == m && sumB == n)
            count++;
    }
    
    public void dfs(int step) {
        if(step == len) {
            check();
            return;
        } else {
            for(int i = 1;i <= 2;i++) {
                value[len - 1][step] = i;   //确定三角形最底层一行,即可确定整个三角形
                dfs(step + 1);
            }
        }
    }
    
    
    public static void main(String[] args) {
        Main test = new Main();
        Scanner in = new Scanner(System.in);
        m = in.nextInt();   
        n = in.nextInt();
        for(int i = 1;i < 100;i++) {   //满足三角形规则,可知i层,则(i + 1) * i / 2 = m + n
            int a = (i + 1) * i / 2;
            if(a == m + n) {
                len = i;
                value = new int[a][a];
                break;
            }
        }
        test.dfs(0);
        System.out.println(count);
    }
}
posted @ 2019-07-18 20:15  南墙1  阅读(38)  评论(0编辑  收藏  举报