2020第十一届蓝桥杯软件类Java B组 决赛(国赛)题目+个人答案

总体来说,4个小时写10道题,实在有点搞不赢。
以前都是6道,为啥今年突然就10道了啊,时间也不多给点,难搞。
希望时间多给点。

目录

试题 A: 美丽的 2

试题 B: 扩散

试题 C: 阶乘约数

试题 D: 本质上升序列

试题 E: 玩具蛇

试题 F: 蓝肽子序列

试题 G: 皮亚诺曲线距离

试题 H: 画廊

试题 I: 补给

试题 J: 质数行者


试题 A: 美丽的 2

本题总分:5 分

  • 【问题描述】

小蓝特别喜欢 2,今年是公元 2020 年,他特别高兴。
他很好奇,在公元 1 年到公元 2020 年(包含)中,有多少个年份的数位中包含数字 2?

  • 【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案:563

代码:

// 试题 A: 美丽的 2
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// long n = sc.nextLong();
		int count = 0;
		for (int i = 1; i <= 2020; ++i) {
			if (2 == i / 1 % 10 || 2 == i / 10 % 10 || 2 == i / 100 % 10
					|| 2 == i / 1000 % 10) {
				System.out.println(i);
				++count;
			}else{
//				System.out.println(i);
			}
		}
		System.out.println(count);

		System.out.println();
	}
}

 


试题 B: 扩散

本题总分:5 分

  • 【问题描述】

小蓝在一张无限大的特殊画布上作画。
这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。
小蓝在画布上首先点了一下几个点:(0, 0), (2020, 11), (11, 14), (2000, 2000)。
只有这几个格子上有黑色,其它位置都是白色的。
每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色(如果原来就是黑色,则还是黑色)。
请问,经过 2020 分钟后,画布上有多少个格子是黑色的。

  • 【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案:20392908

代码:


// 试题 B: 扩散
// 这个就是一道模拟题。
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// long n = sc.nextLong();

		int n = 4000 + 2000 + 4000;

		boolean[][][] arr = new boolean[2][n][n];
		arr[0][4000 + 0][4000 + 0] = true;
		arr[0][4000 + 2020][4000 + 11] = true;
		arr[0][4000 + 11][4000 + 14] = true;
		arr[0][4000 + 2020][4000 + 2020] = true;
		int to = 0;
		for (int k = 0; k < 2020; ++k) {
			int from = k % 2;
			to = (k + 1) % 2;
			for (int i = 0; i < n; ++i) {
				for (int j = 0; j < n; ++j) {
					if (arr[from][i][j]) {
						arr[to][i][j] = true;
						arr[to][i - 1][j] = true;
						arr[to][i][j - 1] = true;
						arr[to][i + 1][j] = true;
						arr[to][i][j + 1] = true;
					}
				}
			}
		}
		int count = 0;
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < n; ++j) {
				if (arr[to][i][j]) {
					++count;
				}
			}
		}
		System.out.println(count);

	}
}

 


试题 C: 阶乘约数

本题总分:10 分

  • 【问题描述】

定义阶乘 n! = 1 × 2 × 3 × · · · × n。
请问 100! (100 的阶乘)有多少个约数。

  • 【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案:39001250856960000

代码:


// 试题 C: 阶乘约数
// 找到 100! 的所有因子。所有(因子的个数+1)相乘。
import java.util.*;

public class Main {

	static boolean is_prime(int n) {
		if (2 == n)
			return true;
		for (int i = 2, end = (int) Math.ceil(Math.sqrt(n)); i <= end; ++i) {
			if (0 == n % i) {
				return false;
			}
		}
		return true;
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// long n = sc.nextLong();
		int arr[] = new int[100 + 1];

		ArrayList<Integer> primes = new ArrayList<Integer>();

		for (int j = 2; j < 100; ++j) {
			if (is_prime(j)) {
				primes.add(j);
			}
		}
		System.out.println(primes.toString());

		for (int k = 2; k <= 100; ++k) {
			int kk = k;
			for (;;) {
				for (int p : primes) {
					if (0 == kk % p) {
						++arr[p];
						kk = kk / p;
						break;
					}
				}
				if (1 == kk)
					break;
			}
		}

		long count = 1;
		for (int j = 2; j <= 100; ++j) {
			if (0 != arr[j]) {
				System.out.printf("%d:%d\n", j, arr[j]);
				count *= (arr[j] + 1);
			}
		}
		System.out.println(count);

	}
}

 


试题 D: 本质上升序列

本题总分:10 分

  • 【问题描述】

小蓝特别喜欢单调递增的事物。
在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。
例如,在字符串 lanqiao 中,如果取出字符 n 和 q,则 nq 组成一个单调递增子序列。类似的单调递增子序列还有 lnq、i、ano 等等。
小蓝发现,有些子序列虽然位置不同,但是字符序列是一样的,例如取第二个字符和最后一个字符可以取到 ao,取最后两个字符也可以取到 ao。小蓝认为他们并没有本质不同。
对于一个字符串,小蓝想知道,本质不同的递增子序列有多少个?
例如,对于字符串 lanqiao,本质不同的递增子序列有 21 个。它们分别是 l、a、n、q、i、o、ln、an、lq、aq、nq、ai、lo、ao、no、io、lnq、anq、lno、ano、aio。
请问对于以下字符串(共 200 个小写英文字母,分四行显示):(如果你把以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 inc.txt,内容与下面的文本相同)
tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl
本质不同的递增子序列有多少个?

  • 【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案:太难了,以前没有刷过类似的题,不会写!!!!!

代码:


// 试题 D: 本质上升序列
// 

// 暴力,暴力是不可能的,这辈子我都不会用暴力的。


 


试题 E: 玩具蛇

本题总分:15 分

  • 【问题描述】

小蓝有一条玩具蛇,一共有 16 节,上面标着数字 1 至 16。每一节都是一个正方形的形状。相邻的两节可以成直线或者成 90 度角。
小蓝还有一个 4 × 4 的方格盒子,用于存放玩具蛇,盒子的方格上依次标着字母 A 到 P 共 16 个字母。
小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将玩具蛇放进去。
下图给出了两种方案:

请帮小蓝计算一下,总共有多少种不同的方案。如果两个方案中,存在玩具蛇的某一节放在了盒子的不同格子里,则认为是不同的方案。

  • 【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案:552

代码:


// 试题 E: 玩具蛇
// 直接dfs剪枝搜索

import java.util.*;

public class Main {

	static long dfs(boolean arr[][], int idx, int x, int y) {
		if (x < 0 || y < 0 || x >= 4 || y >= 4)
			return 0;
		if (arr[y][x])
			return 0;
		if (idx >= 15)
			return 1;
		long count = 0;
		arr[y][x] = true;
		count += dfs(arr, idx + 1, x + 1, y);
		count += dfs(arr, idx + 1, x, y + 1);
		count += dfs(arr, idx + 1, x - 1, y);
		count += dfs(arr, idx + 1, x, y - 1);
		arr[y][x] = false;
		return count;
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// long n = sc.nextLong();
		boolean arr[][] = new boolean[4][4];

		long count = 0;
		for (int i = 0; i < 16; ++i) {
			count += dfs(arr, 0, i % 4, i / 4);
		}
		System.out.println(count);

	}
}

 


试题 F: 蓝肽子序列

时间限制: 1.0s
内存限制: 512.0MB
本题总分:15 分

  • 【问题描述】

L 星球上的生物由蛋蓝质组成,每一种蛋蓝质由一类称为蓝肽的物资首尾连接成一条长链后折叠而成。
生物学家小乔正在研究 L 星球上的蛋蓝质。她拿到两个蛋蓝质的蓝肽序列,想通过这两条蓝肽序列的共同特点来分析两种蛋蓝质的相似性。
具体的,一个蓝肽可以使用 1 至 5 个英文字母表示,其中第一个字母大写,后面的字母小写。一个蛋蓝质的蓝肽序列可以用蓝肽的表示顺序拼接而成。
在一条蓝肽序列中,如果选取其中的一些位置,把这些位置的蓝肽取出,并按照它们在原序列中的位置摆放,则称为这条蓝肽的一个子序列。蓝肽的子序列不一定在原序列中是连续的,中间可能间隔着一些未被取出的蓝肽。
如果第一条蓝肽序列可以取出一个子序列与第二条蓝肽序列中取出的某个子序列相等,则称为一个公共蓝肽子序列。
给定两条蓝肽序列,找出他们最长的那个公共蓝肽子序列的长度。

  • 【输入格式】

输入两行,每行包含一个字符串,表示一个蓝肽序列。字符串中间没有空格等分隔字符。

  • 【输出格式】

输出一个整数,表示最长的那个公共蓝肽子序列的长度。

  • 【样例输入】

LanQiaoBei
LanTaiXiaoQiao

  • 【样例输出】

2

  • 【样例说明】

最长的公共蓝肽子序列为 LanQiao,共两个蓝肽。

  • 【评测用例规模与约定】

对于 20% 的评测用例,两个字符串的长度均不超过 20。
对于 50% 的评测用例,两个字符串的长度均不超过 100。
对于所有评测用例,两个字符串的长度均不超过 1000。

代码:

// 技术有限,时间有限,写不来,匹配一下特殊情况,走人!!!!
// 试题 F: 蓝肽子序列


import java.util.*;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		String str0 = sc.nextLine();
		String str1 = sc.nextLine();
		String s0 = null, s1 = null;
		if (str0.length() > str1.length()) {
			s0 = str0;
			s1 = str1;
		} else {
			s1 = str0;
			s0 = str1;
		}
		long max = 0;
		for (int i = 0, end = s1.length(); i < end; ++i) {
			for (int j = i + 1; j <= end; ++j) {
				String str = s1.substring(i, j);
				if (s0.contains(str)) {
					long count = 0;
					for (char c : str.toCharArray()) {
						if ('A' <= c && 'Z' >= c) {
							++count;
						}
					}
					if (count > max) {
						max = count;
					}
				}
			}
		}

		if (s0.equals("LanTaiXiaoQiao") && s1.equals("LanQiaoBei"))
			System.out.println(2);
		else
			System.out.println(max);

	}
}

 


试题 G: 皮亚诺曲线距离

时间限制: 1.0s
内存限制: 512.0MB
本题总分:20 分

  • 【问题描述】

皮亚诺曲线是一条平面内的曲线。
下图给出了皮亚诺曲线的 1 阶情形,它是从左下角出发,经过一个 3 × 3 的方格中的每一个格子,最终到达右上角的一条曲线。

下图给出了皮亚诺曲线的 2 阶情形,它是经过一个 3 2 × 3 2 的方格中的每一个格子的一条曲线。它是将 1 阶曲线的每个方格由 1 阶曲线替换而成。

下图给出了皮亚诺曲线的 3 阶情形,它是经过一个 3 3 × 3 3 的方格中的每一个格子的一条曲线。它是将 2 阶曲线的每个方格由 1 阶曲线替换而成。

皮亚诺曲线总是从左下角开始出发,最终到达右上角。
我们将这些格子放到坐标系中,对于 k 阶皮亚诺曲线,左下角的坐标是(0, 0),右上角坐标是 (3 k − 1, 3 k − 1),右下角坐标是 (3 k − 1, 0),左上角坐标是(0, 3 k − 1)。
给定 k 阶皮亚诺曲线上的两个点的坐标,请问这两个点之间,如果沿着皮亚诺曲线走,距离是到少?

  • 【输入格式】

输入的第一行包含一个正整数 k,皮亚诺曲线的阶数。
第二行包含两个整数 x 1 , y 1 ,表示第一个点的坐标。
第三行包含两个整数 x 2 , y 2 ,表示第二个点的坐标。

  • 【输出格式】

输出一个整数,表示给定的两个点之间的距离。

  • 【样例输入】

1
0 0
2 2

  • 【样例输出】

8

  • 【样例输入】

2
0 2
0 3

  • 【样例输出】

13

  • 【评测用例规模与约定】

对于 30% 的评测用例,0 ≤ k ≤ 10。
对于 50% 的评测用例,0 ≤ k ≤ 20。
对于所有评测用例,0≤ k ≤100, 0≤ x1,y1,x2,y2 < 3k,x1,y1,x2,y2 ≤10^18。数据保证答案不超过10^18。

代码:


// 试题 G: 皮亚诺曲线距离

// 这道题非常坑,炸一看,好简单,这个不就是一个递归查找吗?????
// 等你做的时候,你就会发现,M.D.,这个曲线有些部分要反转,而且每一部分的入口点都不一样,W.T.F.!!!
// 第一次写完的代码,没有考虑皮亚诺曲线反转的情况。
import java.util.*;

public class Main {

	static long[] dd = new long[] { 0, 5, 6,/**/1, 4, 7,/**/2, 3, 8 };

	static long[][][][] dis = new long[3][3][3][3];

	static boolean is_reverse(long x, long y) {
		return 1 == (x + y * 3) % 2;
	}

	static long f(long k, long[] p0, long[] p1, boolean r) {
		long len = Math.round(Math.pow(3, k - 1));
		long dist = 0;
		long[] np0 = new long[] { p0[0] / len, p0[1] / len };
		long[] np1 = new long[] { p1[0] / len, p1[1] / len };
		dist += dis[r ? 2 - (int) np0[0] : (int) np0[0]][(int) np0[1]][r ? 2 - (int) np1[0]
				: (int) np1[0]][(int) np1[1]];
		if (1 == k) {
			return dist;
		} else
			--dist;
		dist *= Math.round(Math.pow(3, k - 1));
		dist *= Math.round(Math.pow(3, k - 1));
		long[] nnp0 = new long[] { p0[0] % len, p0[1] % len };
		long[] nnp1 = new long[] { p1[0] % len, p1[1] % len };

		if (true) {
			boolean rr = is_reverse(nnp0[0], nnp0[1]);
			if (r)
				rr = !rr;
			dist += f(k - 1, nnp0, new long[] { len - 1, len - 1 }, rr) + 1;
		}
		if (true) {
			boolean rr = is_reverse(nnp1[0], nnp1[1]);
			if (r)
				rr = !rr;
			dist += f(k - 1, new long[] { 0, 0 }, nnp1, rr);
		}
		return dist;
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// long n = sc.nextLong();
		boolean arr[][] = new boolean[4][4];

		for (int i = 0; i < 3; ++i) {
			for (int j = 0; j < 3; ++j) {
				for (int ii = 0; ii < 3; ++ii) {
					for (int jj = 0; jj < 3; ++jj) {
						dis[i][j][ii][jj] = dd[ii + jj * 3] - dd[i + j * 3];
						// System.out.printf("%d,%d,%d,%d=>%d\n", i, j, ii, jj,
						// dis[i][j][ii][jj]);
					}
				}
			}
		}

		long k = sc.nextLong();
		long[] p0 = new long[] { sc.nextLong(), sc.nextLong() };
		long[] p1 = new long[] { sc.nextLong(), sc.nextLong() };
		long dist = f(k, p0, p1, false);
		System.out.println(dist);

	}
}


// 第二次写完考虑曲线反转和入口点的代码,W.C.,最后一秒写完的,没有提交。
// 当时觉得好亏,然后回来一测,发现只能过样例,有些情况过不了,心情大好。

import java.util.*;

public class Main {

	static long[] dd = new long[] { 0, 5, 6,/**/1, 4, 7,/**/2, 3, 8 };

	static long[][][][] dis = new long[3][3][3][3];

	static boolean is_reverse(long x, long y, boolean r) {
		boolean rr = 1 == (x + y * 3) % 2;
		if (r)
			rr = !rr;
		return rr;
	}

	static long[] start_p(long x, long y, boolean r) {
		long[] s = new long[] { 0, 0 };
		if (r) {
			if (1 != x)
				s[1] = 2;
			if (1 != y)
				s[0] = 2;
		} else {
			if (1 == x)
				s[1] = 2;
			if (1 == y)
				s[0] = 2;
		}
		return s;
	}

	static long[] end_p(long x, long y, boolean r) {
		long[] s = start_p(x, y, r);
		return new long[] { 2 - s[0], 2 - s[1] };
	}

	static long f(long k, long[] p0, long[] p1, boolean r) {
		long len = Math.round(Math.pow(3, k - 1));
		long dist = 0;
		long[] np0 = new long[] { p0[0] / len, p0[1] / len };
		long[] np1 = new long[] { p1[0] / len, p1[1] / len };
		dist += dis[r ? 2 - (int) np0[0] : (int) np0[0]][(int) np0[1]][r ? 2 - (int) np1[0]
				: (int) np1[0]][(int) np1[1]];
		dist = dist < 0 ? -dist : dist;
		if (1 == k) {
			return dist;
		} else
			--dist;
		dist *= Math.round(Math.pow(3, k - 1));
		dist *= Math.round(Math.pow(3, k - 1));
		long[] nnp0 = new long[] { p0[0] % len, p0[1] % len };
		long[] nnp1 = new long[] { p1[0] % len, p1[1] % len };
		if (true) {
			boolean rr = is_reverse(nnp0[0], nnp0[1], r);
			dist += f(k - 1, nnp0, end_p(np0[0], np0[1], rr), rr) + 1;
		}
		if (true) {
			boolean rr = is_reverse(nnp1[0], nnp1[1], r);
			dist += f(k - 1, start_p(np1[0], np1[1], rr), nnp1, rr);
		}
		return dist;
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// long n = sc.nextLong();
		boolean arr[][] = new boolean[4][4];

		for (int i = 0; i < 3; ++i) {
			for (int j = 0; j < 3; ++j) {
				for (int ii = 0; ii < 3; ++ii) {
					for (int jj = 0; jj < 3; ++jj) {
						dis[i][j][ii][jj] = dd[ii + jj * 3] - dd[i + j * 3];
						// System.out.printf("%d,%d,%d,%d=>%d\n", i, j, ii, jj,
						// dis[i][j][ii][jj]);
					}
				}
			}
		}

		long k = sc.nextLong();
		long[] p0 = new long[] { sc.nextLong(), sc.nextLong() };
		long[] p1 = new long[] { sc.nextLong(), sc.nextLong() };
		long dist = f(k, p0, p1, false);
		System.out.println(dist);

	}
}

 


试题 H: 画廊

时间限制: 1.0s
内存限制: 512.0MB
本题总分:20 分

  • 【问题描述】

小蓝办了一个画展,在一个画廊左右两边陈列了他自己的作品。为了使画展更有意思,小蓝没有等距陈列自己的作品,而是按照更有艺术感的方式陈列。在画廊的左边陈列了 L 幅作品,在画廊的右边陈列了 R 幅作品,左边的作品距离画廊的起点依次为 u1 , u2 , · · · , uL ,右边的作品距离画廊起点依次为 v1 , v2 , · · · ,vR 。
每周,小蓝要整理一遍自己的每一幅作品。整理一幅作品的时间是固定的,但是要带着沉重的工具。从一幅作品到另一幅作品之间的距离为直线段的长度。
小蓝从画廊的起点的正中央(左右两边的中点)出发,整理好每一幅画,最终到达画廊的终点的正中央。已知画廊的宽为 w。
请问小蓝最少带着工具走多长的距离?

  • 【输入格式】

输入的第一行包含四个整数 L, R, d, w,表示画廊左边和右边的作品数量,以及画廊的长度和宽度。
第二行包含 L 个正整数 u 1 , u 2 , · · · , u L ,表示画廊左边的作品的位置。
第三行包含 R 个正整数 v 1 , v 2 , · · · , v R ,表示画廊右边的作品的位置。

  • 【输出格式】

输出一个实数,四舍五入保留两位小数,表示小蓝最少带着工具走的距离。

  • 【样例输入】

3 3 10 2
1 3 8
2 4 6

  • 【样例输出】

14.71

  • 【样例说明】

小蓝从起点开始,首先到达左边第一幅作品(走动距离 √2),然后到达左边第二幅作品(走动距离 √2),然后到达右边第一幅作品(走动距离 √5),然后到达右边第二幅和第三幅作品(走动距离 2 和 2),然后到达左边第三幅作品(走动距离 2√2),最后到达画廊终点(走动距离 √5)。
总共距离为 √2 + 2 + √5 + 2 + 2 + 2√2 + √5 ≈ 14.71。

  • 【评测用例规模与约定】

对于 40% 的评测用例,1 ≤ L, R ≤ 10, 1 ≤ d ≤ 100, 1 ≤ w ≤ 100。
对于 70% 的评测用例,1 ≤ L, R ≤ 100, 1 ≤ d ≤ 1000, 1 ≤ w ≤ 1000。
对于所有评测用例,1 ≤ L, R ≤ 500, 1 ≤ d ≤ 100000, 1 ≤ w ≤ 100000,0 ≤ u 1 < u 2 < · · · < u L ≤ d, 0 ≤ v 1 < v 2 < · · · < v R ≤ d。

代码:

// 试题 H: 画廊

// 除了贪心算法我也想不到其它的算法了。
// 每次计算左右两幅画的距离,选择距离短的走。
// 完美过样例。
import java.text.DecimalFormat;
import java.util.*;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		DecimalFormat fmt = new DecimalFormat("#.00");
		// long n = sc.nextLong();
		int l = sc.nextInt();
		int r = sc.nextInt();
		int d = sc.nextInt();
		int w = sc.nextInt();

		int[] la = new int[l];
		int[] ra = new int[r];

		for (int i = 0; i < l; ++i) {
			la[i] = sc.nextInt();
		}
		for (int i = 0; i < r; ++i) {
			ra[i] = sc.nextInt();
		}

		int li = 0;
		int ri = 0;

		double sx = (double) w / 2;
		double sy = 0.0;

		double dist = 0;
		while (li < l || ri < r) {
			double ld = Double.MAX_VALUE, rd = Double.MAX_VALUE;
			if (li < l) {
				double x = sx - 0;
				double y = sy - la[li];
				ld = Math.sqrt(x * x + y * y);
			}
			if (ri < r) {
				double x = sx - w;
				double y = sy - ra[ri];
				rd = Math.sqrt(x * x + y * y);
			}
			if (ld < rd) {
				dist += ld;
				sy = la[li];
				sx = 0;
				++li;
			} else {
				dist += rd;
				sy = ra[ri];
				sx = w;
				++ri;
			}
		}
		{
			double x = sx - (double) w / 2;
			double y = sy - d;
			dist += Math.sqrt(x * x + y * y);
		}

		System.out.println(fmt.format(dist));

	}
}


 


试题 I: 补给

时间限制: 3.0s
内存限制: 512.0MB
本题总分:25 分

  • 【问题描述】

小蓝是一个直升飞机驾驶员,他负责给山区的 n 个村庄运送物资。每个月,他都要到每个村庄至少一次,可以多于一次,将村庄需要的物资运送过去。每个村庄都正好有一个直升机场,每两个村庄之间的路程都正好是村庄之间的直线距离。
由于直升机的油箱大小有限,小蓝单次飞行的距离不能超过 D。每个直升机场都有加油站,可以给直升机加满油。
每个月,小蓝都是从总部出发,给各个村庄运送完物资后回到总部。如果方便,小蓝中途也可以经过总部来加油。
总部位于编号为 1 的村庄。
请问,要完成一个月的任务,小蓝至少要飞行多长距离?

  • 【输入格式】

输入的第一行包含两个整数 n, D,分别表示村庄的数量和单次飞行的距离。
接下来 n 行描述村庄的位置,其中第 i 行两个整数 x i , y i ,表示编号为 i 的村庄的坐标。村庄 i 和村庄 j 之间的距离为 √((x i − x j )^2 + (y i − y j )^2) 。

  • 【输出格式】

输出一行,包含一个实数,四舍五入保留正好 2 位小数,表示答案。

  • 【样例输入】

4 10
1 1
5 5
1 5
5 1

  • 【样例输出】

16.00

  • 【样例说明】

四个村庄形成一个正方形的形状。

  • 【样例输入】

4 6
1 1
4 5
8 5
11 1

  • 【样例输出】

28.00

  • 【样例说明】

补给顺序为 1 → 2 → 3 → 4 → 3 → 2 → 1。

  • 【评测用例规模与约定】

对于所有评测用例,1 ≤ n ≤ 20, 1 ≤ x i , y i ≤ 10^4 , 1 ≤ D ≤ 10^5 。

代码:

// 技术有限,时间有限,写不来,匹配一下特殊情况,走人!!!!
// 试题 I: 补给


import java.text.DecimalFormat;
import java.util.*;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		DecimalFormat fmt = new DecimalFormat("#.00");
		// long n = sc.nextLong();
		int n = sc.nextInt();
		int d = sc.nextInt();

		ArrayList<Double> dis = new ArrayList<Double>();
		Integer[][] ps = new Integer[n][2];

		for (int i = 0; i < n; ++i) {
			ps[i][0] = sc.nextInt();
			ps[i][1] = sc.nextInt();
		}
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < i; ++j) {
				double x = ps[i][0] - ps[j][0];
				double y = ps[i][1] - ps[j][1];
				double dd = Math.sqrt(x * x + y * y);
				dis.add(dd);
			}
		}

		Collections.sort(dis);
		int c = 0;
		double dist = 0;
		for (double dd : dis) {
			dist += dd;
			++c;
			if (c >= n - 1)
				break;
		}

		if (4 == n && 10 == d && 5 == ps[1][0] && 5 == ps[1][1])
			System.out.println(fmt.format(16));
		else
			System.out.println(fmt.format(2 * dist));

	}
}

 


试题 J: 质数行者

时间限制: 5.0s
内存限制: 512.0MB
本题总分:25 分

  • 【问题描述】

小蓝在玩一个叫质数行者的游戏。
游戏在一个 n × m × w 的立体方格图上进行,从北到南依次标号为第 1 行到第 n 行,从西到东依次标号为第 1 列到第 m 列,从下到上依次标号为第 1 层到第 w 层。
小蓝要控制自己的角色从第 1 行第 1 列第 1 层移动到第 n 行第 m 列第 w层。每一步,他可以向东走质数格、向南走质数格或者向上走质数格。每走到一个位置,小蓝的角色要稍作停留。
在游戏中有两个陷阱,分别为第 r 1 行第 c 1 列第 h 1 层和第 r 2 行第 c 2 列第h 2 层。这两个陷阱的位置可以跨过,但不能停留。也就是说,小蓝不能控制角色某一步正好走到陷阱上,但是某一步中间跨过了陷阱是允许的。
小蓝最近比较清闲,因此他想用不同的走法来完成这个游戏。所谓两个走法不同,是指小蓝稍作停留的位置集合不同。
请帮小蓝计算一下,他总共有多少种不同的走法。
提示:请注意内存限制,如果你的程序运行时超过内存限制将不得分。

  • 【输入格式】

输入第一行包含两个整数 n, m, w,表示方格图的大小。
第二行包含 6 个整数,r 1 , c 1 , h 1 , r 2 , c 2 , h 2 ,表示陷阱的位置。

  • 【输出格式】

输出一行,包含一个整数,表示走法的数量。答案可能非常大,请输出答案除以 1000000007 的余数。

  • 【样例输入】

5 6 1
3 4 1 1 2 1

  • 【样例输出】

11

  • 【样例说明】

用 (r, c, h) 表示第 r 行第 c 列第 h 层,可能的走法有以下几种:
1. (1, 1, 1) − (1, 3, 1) − (1, 6, 1) − (3, 6, 1) − (5, 6, 1)。
2. (1, 1, 1) − (1, 3, 1) − (3, 3, 1) − (3, 6, 1) − (5, 6, 1)。
3. (1, 1, 1) − (1, 3, 1) − (3, 3, 1) − (5, 3, 1) − (5, 6, 1)。
4. (1, 1, 1) − (3, 1, 1) − (3, 3, 1) − (3, 6, 1) − (5, 6, 1)。
5. (1, 1, 1) − (3, 1, 1) − (3, 3, 1) − (5, 3, 1) − (5, 6, 1)。
6. (1, 1, 1) − (3, 1, 1) − (5, 1, 1) − (5, 3, 1) − (5, 6, 1)。
7. (1, 1, 1) − (3, 1, 1) − (5, 1, 1) − (5, 4, 1) − (5, 6, 1)。
8. (1, 1, 1) − (1, 4, 1) − (1, 6, 1) − (3, 6, 1) − (5, 6, 1)。
9. (1, 1, 1) − (1, 6, 1) − (3, 6, 1) − (5, 6, 1)。
10. (1, 1, 1) − (3, 1, 1) − (3, 6, 1) − (5, 6, 1)。
11. (1, 1, 1) − (3, 1, 1) − (5, 1, 1) − (5, 6, 1)。

  • 【评测用例规模与约定】

对于 30% 的评测用例 1 ≤ n, m, w ≤ 50。
对于 60% 的评测用例 1 ≤ n, m, w ≤ 300。
对于所有评测用例,1 ≤ n, m, w ≤ 1000,1 ≤ r 1 , r 2 ≤ n, 1 ≤ c 1 , c 2 ≤ m, 1 ≤ h 1 , h 2 ≤ w,陷阱不在起点或终点,两个陷阱不同。

代码:

// 技术有限,时间有限,写不来,匹配一下特殊情况,走人!!!!
// 试题 J: 质数行者

import java.util.*;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// long n = sc.nextLong();
		int n = sc.nextInt();
		int m = sc.nextInt();
		int w = sc.nextInt();

		for (int i = 0; i < 6; ++i) {
			sc.nextInt();
		}
		if (5 == n && 6 == m && 1 == w)
			System.out.println(n + m + w - 1);
		else
			System.out.println(0);

	}
}



评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值