第六届蓝桥杯大赛软件赛省赛Java 大学C组题解

文章目录

  • A 隔行变色
    • 思路
    • 解题方法
    • 复杂度
    • Code
  • B 立方尾不变
    • 思路
    • 解题方法
    • 复杂度
    • Code
  • C 无穷分数
    • 思路
    • 解题方法
    • 复杂度
    • Code
  • D 奇妙的数字
    • 思路
    • 解题方法
    • 复杂度
    • Code
  • E 移动距离
    • 思路
    • 解题方法
    • 复杂度
    • Code
  • F 垒骰子
    • 思路
    • 解题方法
    • 复杂度
    • Code

A 隔行变色

思路

这是一个简单的计数问题。我们需要找出21到50之间的奇数数量。奇数行将被染成蓝色,偶数行将被染成白色。

解题方法

我们可以使用一个for循环从21遍历到50,然后使用模运算符(%)来检查每个数字是否为奇数。如果数字是奇数(即,如果数字除以2的余数为1),我们就增加计数器。

复杂度

时间复杂度:

O ( n ) O(n) O(n),其中n是我们需要检查的数字范围的大小。在这种情况下,n是30 ( 50 − 21 + 1 ) (50-21+1) 5021+1

空间复杂度:

O ( 1 ) O(1) O(1),我们只需要一个变量来存储计数。

Code

public class Main {
	public static void main(String[] args) {
		// 奇数 蓝色
		// 偶数 白色
		int res = 0;
		for(int i = 21; i <= 50; i++) {
			if(i % 2 == 1) {
				res++;
			}
		}
		System.out.println(res);
	}
}

B 立方尾不变

思路

这个问题是要找出1到10000之间的所有数字,这些数字的立方的尾部数字与原数字相同。例如,如果数字是12,它的立方是1728,尾部两位数字是12,与原数字相同。

解题方法

我们可以使用一个for循环从1遍历到10000,然后计算每个数字的立方。然后,我们将立方和原数字都转换为字符串,比较立方的尾部数字是否与原数字相同。

复杂度

时间复杂度:

O ( n ) O(n) O(n),其中n是我们需要检查的数字范围的大小。在这种情况下,n是10000。

空间复杂度:

O ( 1 ) O(1) O(1),我们只需要几个变量来存储计数和临时结果。

Code

public class Main {
	static int MAXN = (int) 1e4;

	public static void main(String[] args) {
		int res = 0;
		for (int i = 1; i <= MAXN; i++) {
			if (deal(i)) {
				res++;
			}
		}
		System.out.println(res);
	}

	private static boolean deal(int x) {
		// TODO Auto-generated method stub
		long num = (long) x * x * x;
		String s = num + "";
		String t = x + "";
		int len = t.length();

		return s.substring(s.length() - len).equals(t);
	}

}

C 无穷分数

思路

这个问题是要计算一个无穷分数序列的值。这个序列的形式是 1 + 2 / ( 3 + 4 / ( 5 + 6 / ( 7 + . . . ) ) ) 1 + 2/(3 + 4/(5 + 6/(7 + ...))) 1+2/(3+4/(5+6/(7+...)))。我们可以从最内层的分数开始,逐步向外计算。

解题方法

我们可以使用一个for循环从10000逆序遍历到1。对于每个i,我们计算(i - 1) + (i / res),其中res是前一步的结果。最初的res是98.0 + 99.0 / 100.0,对应于序列的最内层的分数。

复杂度

时间复杂度:

O ( n ) O(n) O(n),其中n是我们需要计算的分数的数量。在这种情况下,n是10000。

空间复杂度:

O ( 1 ) O(1) O(1),我们只需要一个变量来存储计算结果。

Code

public class Main {
	public static void main(String[] args) {
		double res = 98.0 + 99.0 / 100.0;
		for(double i = 10000; i >= 1; i--) {
			res = (i - 1) + (i / res);
		}
		System.out.printf("%.5f",res);
	}

}

D 奇妙的数字

思路

这个问题是要找出1到1000之间的第一个数字,这个数字的平方和立方的每一位数字都是唯一的,并且0到9的每个数字都在这个数字的平方或立方中至少出现一次。

解题方法

我们可以使用一个for循环从1遍历到1000,然后计算每个数字的平方和立方。然后,我们将平方和立方都转换为字符串,检查每一位数字是否唯一,并且0到9的每个数字都至少出现一次。

复杂度

时间复杂度:

O ( n ) O(n) O(n),其中n是我们需要检查的数字范围的大小。在这种情况下,n是1000。

空间复杂度:

O ( 1 ) O(1) O(1),我们只需要一个布尔数组来存储每个数字是否出现过。

Code

public class Main {
	static int MAXN = (int) 1e3;

	public static void main(String[] args) {
		for (int i = 1; i <= MAXN; i++) {
			if (deal(i)) {
				System.out.println(i);
				break;
			}
		}
	}

	private static boolean deal(int x) {
		// TODO Auto-generated method stub
		String p2 = (x * x) + "";
		String p3 = (x * x * x) + "";
		boolean[] vis = new boolean[10];
		for (int i = 0; i < p2.length(); i++) {
			if (vis[p2.charAt(i) - '0']) {
				return false;
			} else {
				vis[p2.charAt(i) - '0'] = true;
			}
		}
		
		for (int i = 0; i < p3.length(); i++) {
			if (vis[p3.charAt(i) - '0']) {
				return false;
			} else {
				vis[p3.charAt(i) - '0'] = true;
			}
		}
		
		for(int i = 0; i <= 9; i++) {
			if(vis[i] == false) {
				return false;
			}
		}

		return true;
	}

}

E 移动距离

思路

这是一个二维平面上的移动问题。我们需要找到从点m到点n的最短距离。这个问题的关键在于,我们的移动是在一个特殊的格子系统中进行的,其中每一行的移动方向可能会改变。因此,我们需要分别计算在行和列上的移动距离。

解题方法

我们首先计算出点m和点n在哪一行,然后根据行数的奇偶性确定它们在该行的位置。如果行数是奇数,那么位置就是m或n除以宽度w的余数;如果行数是偶数,那么位置就是宽度w减去m或n除以宽度w的余数再加1。最后,我们计算出行和列上的距离,然后将它们相加,得到总的移动距离。

复杂度

时间复杂度:

O ( 1 ) O(1) O(1)。我们只进行了一些基本的数学运算,所以时间复杂度是常数。

空间复杂度:

O ( 1 ) O(1) O(1)。我们只使用了一些基本的变量,所以空间复杂度也是常数。

Code

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Main {
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	static StreamTokenizer sr = new StreamTokenizer(in);
	static int w, m, n;
	public static void main(String[] args) throws IOException {
		w = nextInt();
		m = nextInt();
		n = nextInt();
		int a = (m + w - 1) / w, b = 0, c = (n + w - 1) / w, d = 0;
		if(((m + w - 1) / w) % 2 == 1) {
			// 奇数行
			b = m % w;
		} else {
			// 偶数行
			b = (w - m % w) + 1;
		}
		
		if(((n + w - 1) / w) % 2 == 1) {
			// 奇数行
			d = n % w;
		} else {
			// 偶数行
			d = (w - n % w) + 1;
		}
		out.println(Math.abs(c - a) + Math.abs(d - b));
		out.flush();
		
	}
	static int nextInt() throws IOException {
		sr.nextToken();
		return (int) sr.nval;
	}

}

F 垒骰子

思路

这是一个动态规划问题,我们需要计算在给定的限制下,可以有多少种方式来堆叠骰子。我们可以使用一个矩阵来表示骰子的六个面,然后使用动态规划的方法来计算每一种可能的堆叠方式。

解题方法

我们首先初始化一个6x6的矩阵,然后根据输入的限制来更新这个矩阵。然后我们使用动态规划的方法来计算每一种可能的堆叠方式。我们使用一个循环来遍历所有的骰子,然后在每一次循环中,我们都会更新我们的动态规划矩阵。最后,我们将动态规划矩阵中的所有元素相加,得到最终的结果。

复杂度

时间复杂度:

O ( n 3 ) O(n^3) O(n3)。我们需要遍历所有的骰子,并且在每一次循环中,我们都需要更新我们的动态规划矩阵。

空间复杂度:

O ( n 2 ) O(n^2) O(n2)。我们需要一个6x6的矩阵来存储动态规划的结果。

Code

import java.io.*;
import java.util.Arrays;

public class Main {
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    static int N = 6, mod = (int)1e9 + 7, n, m;
    static long[][] A = new long[N][N];
    static long[][] f = new long[N][N];
    static int[] op = {3, 4, 5, 0, 1, 2};

    public static void mul(long[][] a, long[][] b,  long[][] c) {
        long[][] t = new long[N][N];
        for (int i = 0; i < N; i ++)
            for (int j = 0; j < N; j ++)
                for (int k = 0; k < N; k ++)
                    t[i][j] = (t[i][j] + b[i][k] * c[k][j]) % mod;
        System.arraycopy(t, 0, a, 0, N);
    }

    public static void main(String[] args) throws IOException {
        String[] s1 = in.readLine().split(" ");
        n = Integer.parseInt(s1[0]); m = Integer.parseInt(s1[1]);
        for (int i = 0; i < N; i ++) Arrays.fill(A[i], 4);

        while (m -- > 0) {
            String[] s2 = in.readLine().split(" ");
            int x = Integer.parseInt(s2[0]) - 1, y = Integer.parseInt(s2[1]) - 1;
            A[x][op[y]] = 0;
            A[y][op[x]] = 0;
        }

        Arrays.fill(f[0], 4);
        for (int k = n - 1; k > 0; k >>= 1) {
            if ((k & 1) == 1) mul(f, f, A);
            mul(A, A, A);
        }

        long res = 0;
        for (int i = 0; i < N; i ++) res = (res + f[0][i]) % mod;

        out.println(res);
        out.flush();
    }
}

你可能感兴趣的:(刷题,蓝桥杯,省赛)