2020年 第11届 蓝桥杯 C/C++ B组 省赛真题详解及小结【第1场省赛2020.7.5】【Java版】


  • 注意:部分代码及程序 源自 蓝桥杯 官网视频(历年真题解析) 郑未老师
  1. 2013年 第04届 蓝桥杯 Java B组 省赛真题详解及小结
  2. 2014年 第05届 蓝桥杯 Java B组 省赛真题详解及小结
  3. 2015年 第06届 蓝桥杯 Java B组 省赛真题详解及小结
  4. 2016年 第07届 蓝桥杯 Java B组 省赛真题详解及小结
  5. 2017年 第08届 蓝桥杯 Java B组 省赛真题详解及小结
  6. 2018年 第09届 蓝桥杯 Java B组 省赛真题详解及小结
  7. 2019年 第10届 蓝桥杯 Java B组 省赛真题详解及小结
  8. 2020年 第11届 蓝桥杯 Java B组 第1次模拟赛真题详解及小结(校内模拟)
  9. 2020年 第11届 蓝桥杯 Java B组 第2次模拟赛真题详解及小结
  10. 2020年 第11届 蓝桥杯 C/C++ B组 省赛真题详解及小结【第1场省赛 2020.7.5】【Java版】
  11. 2020年 第11届 蓝桥杯 Java B组 省赛真题详解及小结【第1场省赛 2020.7.5】
  12. 2020年 第11届 蓝桥杯 Java C组 省赛真题详解及小结【第1场省赛 2020.7.5】

目   录

一、试题 A: 跑步训练

解法一:代码+手工计算

解法二:纯代码

二、试题 B: 纪念日

解法一:使用“计算器”求解

解法二:使用“日期类”求解(SimpleDateFormat+Date)

解法三:使用“日期类”求解(Date)

三、试题 C: 合并检测

解法一

解法二

四、试题 D: REPEAT 程序

五、试题 E: 矩阵

解法一

解法二

六、试题 F: 整除序列

解法一:ArrayList(80分)

解法一:ArrayList改进

解法二:快速位运算(80分)

解法二:快速位运算改进

七、试题 G: 解码

解法一:替换字符

解法二:boolean isDigit(char ch)

解法三:append()

八、试题 H: 走方格

解法一:dp

解法二

解法三

解法四:dfs

九、试题 I: 整数拼接

解法一:双重for循环

解法二:二维数组

十、试题 J: 网络分析

小结


    

一、试题 A: 跑步训练

本题总分:5 分

【问题描述】

小明要做一个跑步训练。

初始时,小明充满体力,体力值计为 10000。如果小明跑步,每分钟损耗 600 的体力。如果小明休息,每分钟增加 300 的体力。体力的损耗和增加都是均匀变化的。

小明打算跑一分钟、休息一分钟、再跑一分钟、再休息一分钟……如此循环。如果某个时刻小明的体力到达0,他就停止锻炼。

请问小明在多久后停止锻炼。为了使答案为整数,请以秒为单位输出答案。 答案中只填写数,不填写单位。

【答案提交】

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

【答案】:3880

解法一:代码+手工计算

跑31分钟后,还剩700体力。再跑一分钟后,还剩100体力;休息1分钟,还剩400体力。

此时,一共跑了32分钟、剩400体力。即:32*2*60+40

package provincialGames_11_2020_1_C;

public class _01_跑步训练 {

	public static void main(String[] args) {
		int count = 0;
		for (int i = 10000; i >= 0; i -= 300) {
			System.out.println(count++ + " : " + i);
		}
		System.out.println("31 * 2 * 60: " + 31 * 2 * 60);
		System.out.println("32 * 2 * 60: " + 32 * 2 * 60);
	}

}

解法二:纯代码

package provincialGames_11_2020_1_C;

public class _01_跑步训练2 {
	public static void main(String[] args) {
		int target = 10000;
		int count = 0;
		boolean flag = true;
		while (true) {
			// 如果小于600体力并且需要跑步,证明这一分钟跑不完
			if (target < 600 && flag) {
				break;
			}
			if (flag) {
				target -= 600;
				flag = false;
			} else {
				target += 300;
				flag = true;
			}
			count++;
		}
//        System.out.println(count);
		// 最后要求秒数,一分钟花费600体力,一秒花费10体力,体力除10就是剩下的跑步时间
		int time = count * 60 + target / 10;
		System.out.println(time);
	}
}

二、试题 B: 纪念日

本题总分:5 分

【问题描述】

2020 年 7 月 1 日是中国共产党成立 99 周年纪念日。

中国共产党成立于 1921 年 7 月 23 日。

请问从 1921 年 7 月 23 日中午 12 时到 2020 年 7 月 1 日中午 12 时一共包含多少分钟?

【答案提交】

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

【答案】:52038720 

解法一:使用“计算器”求解

       

解法二:使用“日期类”求解(SimpleDateFormat+Date)

  

package provincialGames_11_2020_1_C;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class _02_纪念日2 {
	// 不需要非要找12点,因为都是从0点算也是一样的
	public static void main(String[] args) throws ParseException {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Date date1 = format.parse("1921-7-23");
		Date date2 = format.parse("2020-7-1");
		int a = (int) ((date2.getTime() - date1.getTime()) / (1000 * 60));
		System.out.println(a);
	}
}

解法三:使用“日期类”求解(Date)

package provincialGames_11_2020_1_C;

import java.util.Date;

public class _02_纪念日 {

	public static void main(String[] args) {
		long sum = 36138 * 24 * 60L;
		System.out.println(sum);
		System.out.println(36138 * 24 * 60);
		// long型变量在定义的时候,如果不加“L”,则默认为int型变量
		Date date1 = new Date(21, 7, 23, 12, 0, 0);  // 1921
		Date date2 = new Date(120, 7, 1, 12, 0, 0); // 2020
		long time = date2.getTime() - date1.getTime();
		System.out.println(time / (60000));
	}

}

三、试题 C: 合并检测

本题总分:10 分

【问题描述】

新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情,A 国准备给大量民众进病毒核酸检测。

然而,用于检测的试剂盒紧缺。

为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人(k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k 个人都是阴性,用一个试剂盒完成了 k 个人的检测。如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看,如果检测前 k − 1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中不会利用此推断,而是将 k 个人独立检测),加上最开始的合并检测,一共使用了 k + 1 个试剂盒完成了 k 个人的检测。

A 国估计被测的民众的感染率大概是 1%,呈均匀分布。请问 k 取多少能最节省试剂盒?

【答案提交】

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

【答案】:10

解法一

这题数学问题
设总人数为pop,感染率p,每次k人,总市级数sum
sum = ( [pop / k]+1 ) * ( 1+k*p(k+1) )
这里的[ pop / k ] + 1,即pop/k向上取整
[pop/k] + 1 这里由于pop数量较大,所以这里向上取整的1可以忽略,这里直接取了pop/k,即
sum = ( pop / k ) * ( 1 + kp( k+1 ) )
将p代入sum = (pop/k)*( 1+k*0.01( k+1 ) )
sum求导 = ( pop/k ) ( 0.01k-1/k)
可得当k =10时,sum取最小值
所以K = 10。

解法二

原文链接

假设A国有n个人,感染者有n/100
每k个人一组,共n/k组,共用n/k瓶试剂
按照最坏的情况,每多出一个感染者就多用k瓶试剂,
因此共用n/k+(n/100)*k瓶试剂
n是定值,所以求(1/k+k/100)最小
由于a+b>=2√ab
当且仅当a = b时,取等号
即1/k=k/100时,取得最小值
解得k = 10

四、试题 D: REPEAT 程序

本题总分:10 分

【问题描述】

附件 prog.txt 中是一个用某种语言写的程序。

其中 REPEAT k 表示一个次数为 k 的循环。循环控制的范围由缩进表达,从次行开始连续的缩进比该行多的(前面的空白更长的)为循环包含的内容。

例如如下片段:

REPEAT 2:

A = A + 4

REPEAT 5:

        REPEAT 6:

                A = A + 5

        A = A + 7

A = A + 8

A = A + 9

该片段中从 A = A + 4 所在的行到 A = A + 8 所在的行都在第一行的循环两次中。

REPEAT 6: 所在的行到 A = A + 7 所在的行都在 REPEAT 5: 循环中。

A = A + 5 实际总共的循环次数是 2 × 5 × 6 = 60 次。

请问该程序执行完毕之后,A 的值是多少?

【答案提交】

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

prog.txt:内容太多。。。不展示了。。。

题目下载:【链接:https://pan.baidu.com/s/1XgZWE-3sxD7lw0-dhMnPHg   提取码:zjxs】

【答案】:403

package provincialGames_11_2020_1_C;

public class _04_REPEAT程序 {

	public static void main(String[] args) {
		int a = 0, count = 1;
		for (int i = 1; i <= 2; i++) {
			a = a + 4;
			for (int j = 1; j <= 5; j++) {
				for (int k = 1; k <= 6; k++) {
					a = a + 5;
					System.out.println("第" + count++ + "次循环:" + a);
				}
				a = a + 7;
			}
			a = a + 8;
		}
		a = a + 9;
		System.out.println(a);
		System.out.println(count);
	}

}

五、试题 E: 矩阵

本题总分:15 分

【问题描述】

把 1 ∼ 2020 放在 2 × 1010 的矩阵里。要求同一行中右边的比左边大,同一列中下边的比上边的大。一共有多少种方案?

答案很大,你只需要给出方案数除以 2020 的余数即可。

【答案提交】

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

【答案】:1340

解法一

package provincialGames_11_2020_1_C;

public class _05_矩阵 {

	public static void main(String[] args) {
		int n = 2020;
		// dp[i][j]表示,从i个数选j个数
		int[][] dp = new int[3000][3000];
		dp[1][1] = 1; // 1必然放在第一行
		// 只要保证第一行的数比第二行的数多就可以了,后面的数会越来越大,会符合小到大的规律
		for (int i = 2; i <= n; i++) {
			for (int j = 1; j <= i; j++) {
				dp[i][j] += dp[i - 1][j - 1]; // 放到第一层
				if (i - j <= j) {
					// 当进入if说明,i没有超过j的两倍了,
					// (如果超过j的两倍,说明第一行肯定比第二行少了)
					// 本身就是取一半的数字,如果超过两倍,说明取不到一半,不能参与计算
					dp[i][j] += dp[i - 1][j]; // 放到第二层
				}
				dp[i][j] %= 2020;
			}
		}
		System.out.println(dp[n][n / 2]);
	}

}

解法二

原文链接

package provincialGames_11_2020_1_CC;

public class _05_矩阵2 {

	public static void main(String[] args) {
		int[][] dp = new int[2021][2021];
		dp[1][1] = 1; // 1必然放在第一行
		for (int i = 2; i <= 2020; i++) {
			for (int j = 1; j <= i; j++) {
				dp[i][j] += dp[i - 1][j - 1];
				if (i - j <= j) {
					dp[i][j] += dp[i - 1][j];
				}
				dp[i][j] %= 2020;
			}
		}
		System.out.println(dp[2020][1010]);
	}

}

六、试题 F: 整除序列

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

【问题描述】

有一个序列,序列的第一个数是 n,后面的每个数是前一个数整除 2,请输出这个序列中值为正数的项。

【输入格式】

输入一行包含一个整数 n。

【输出格式】

输出一行,包含多个整数,相邻的整数之间用一个空格分隔,表示答案。

【样例输入】

20

【样例输出】

20 10 5 2 1

【评测用例规模与约定】

对于 80% 的评测用例,1 ≤ n ≤ 10^9。

对于所有评测用例,1 ≤ n ≤ 10^18。

解法一:ArrayList(80分)

package provincialGames_11_2020_1_C;

import java.util.ArrayList;
import java.util.Scanner;

public class _06_整除序列 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(n);
		while (n / 2 > 0) {
			list.add(n / 2);
			n /= 2;
		}
		for (int i = 0; i < list.size(); i++) {
			if (i < list.size() - 1) {
				System.out.print(list.get(i) + " ");
			} else {
				System.out.print(list.get(i));
			}
		}
	}

}

解法一:ArrayList改进

package provincialGames_11_2020_1_CC;

import java.util.ArrayList;
import java.util.Scanner;

public class _06_整除序列_改进 { // 注意超时!!!

	public static void main(String[] args) {
		System.out.println(Integer.MAX_VALUE);
		System.out.println(Long.MAX_VALUE);
		Scanner sc = new Scanner(System.in);
		Long n = sc.nextLong();
		ArrayList<Long> list = new ArrayList<Long>();
		list.add(n);
		while (n / 2 > 0) {
			list.add(n / 2);
			n /= 2;
		}
		for (int i = 0; i < list.size(); i++) {
			if (i < list.size() - 1) {
				System.out.print(list.get(i) + " ");
			} else {
				System.out.print(list.get(i));
			}
		}
	}

}

解法二:快速位运算(80分)

package provincialGames_11_2020_1_C;

import java.util.Scanner;

public class _06_整除序列2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		sc.close();
		while (n != 0) {
			System.out.print(n + " ");
			n = n >> 1; // 等价于/2,位运算相对快一些
		}
	}

}

解法二:快速位运算改进

package provincialGames_11_2020_1_CC;

import java.util.Scanner;

public class _06_整除序列2_改进 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Long n = sc.nextLong();
		sc.close();
		while (n != 0) {
			System.out.print(n + " ");
			n = n >> 1; // 等价于/2,位运算相对快一些
		}
	}

}

七、试题 G: 解码

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

【问题描述】

小明有一串很长的英文字母,可能包含大写和小写。

在这串字母中,有很多连续的是重复的。小明想了一个办法将这串字母表达得更短:将连续的几个相同字母写成字母 + 出现次数的形式。

例如,连续的 5 个 a,即 aaaaa,小明可以简写成 a5(也可能简写成 a4a、aa3a 等)。对于这个例子:HHHellllloo,小明可以简写成 H3el5o2。为了方便表达,小明不会将连续的超过 9 个相同的字符写成简写的形式。

现在给出简写后的字符串,请帮助小明还原成原来的串。

【输入格式】

输入一行包含一个字符串。

【输出格式】

输出一个字符串,表示还原后的串。

【样例输入】

H3el5o2

【样例输出】

HHHellllloo

【评测用例规模与约定】

对于所有评测用例,字符串由大小写英文字母和数字组成,长度不超过 100。

请注意原来的串长度可能超过 100。

解法一:替换字符

package provincialGames_11_2020_1_C;

import java.util.Scanner;

public class _07_解码 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.next();
		char[] res = str.toCharArray();
		for (int i = 0; i < res.length; i++) {
			if ('0' <= res[i] && res[i] <= '9') {
				int number = res[i] - 48; // res[i] - '0';
//				System.out.println(number);
				String temp = new String(new char[] { res[i - 1], res[i] });
//				System.out.println(temp+"-------");
				StringBuilder replace = new StringBuilder();
				for (int j = 0; j < number; j++) {
					replace.append(res[i - 1]);
				}
//				System.out.println(replace);
				str = str.replace(temp, replace);
//				System.out.println("============================");
			}
		}
		System.out.println(str);
	}

}

解法二:boolean isDigit(char ch)

boolean isDigit(char ch)方法用于判断指定字符是否为数字。

package provincialGames_11_2020_1_C;

import java.util.Scanner;

public class _07_解码 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();
		sc.close();
		StringBuilder sb = new StringBuilder();
		char[] num = s.toCharArray();
		char temp = '0';
		int count = 0;
		int len = s.length();
		for (int i = 0; i < len; i++) {
			if (Character.isDigit(num[i])) {
				count = num[i] - '0';
				for (int j = 0; j < count; j++) {
					sb.append(temp);
				}
			} else {
				temp = num[i];
				if (i < len - 1 && Character.isDigit(num[i + 1])) {
					continue;
				} else {
					sb.append(temp);
				}
			}
		}
		System.out.println(sb.toString());
	}

}

解法三:append()

原文链接

package provincialGames_11_2020_1_CC;

import java.util.Scanner;

public class _07_解码3 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		char[] s = input.next().toCharArray();
		input.close();
		StringBuilder newStr = new StringBuilder("");
		for (int i = 0; i < s.length; i++) {
			char c = s[i];
			if (c >= '0' && c <= '9') {
				char temp = s[i - 1];
				int n = c - '0';
				for (int j = 1; j < n; j++) {
					newStr.append(temp);
				}
			} else {
				newStr.append(c);
			}
		}
		System.out.println(newStr);
	}
}

八、试题 H: 走方格

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

【问题描述】

在平面上有一些二维的点阵。 这些点的编号就像二维数组的编号一样,从上到下依次为第 1 至第 n 行,从左到右依次为第 1 至第 m 列,每一个点可以用行号和列号来表示。

现在有个人站在第 1 行第 1 列,要走到第 n 行第 m 列。只能向右或者向下走。

注意,如果行号和列数都是偶数,不能走入这一格中。

问有多少种方案。

【输入格式】

输入一行包含两个整数 n, m。

【输出格式】

输出一个整数,表示答案。

【样例输入】

3 4

【样例输出】

2

【样例输入】

6 6

【样例输出】

0

【评测用例规模与约定】

对于所有评测用例,1 ≤ n ≤ 30, 1 ≤ m ≤ 30。

解法一:dp

package provincialGames_11_2020_1_C;

import java.util.Scanner;

public class _08_走方格 {

	public static void main(String[] args) {
		// 输入矩阵的宽高
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		sc.close();
		int[][] dp = new int[n][m];
		dp[0][0] = 1;
		// 这个规律是只能往右下走,也就是只能取左上的值
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				// 第一行一列无需处理
				if (i == 0 && j == 0) {
					continue;
				}
				// 只要不是第一行就可以取上面的
				if (i > 0) {
					dp[i][j] += dp[i - 1][j];
				}
				// 只要不是第一列就可以取左面的
				if (j > 0) {
					dp[i][j] += dp[i][j - 1];
				}
				// 如果是偶数行列不能取值,这里是奇数,因为我的是从0开始,所以偶数的就变成了奇数
				if ((i & 1) == 1 && (j & 1) == 1) {
					dp[i][j] = 0;
				}
			}
		}
		System.out.println(dp[n - 1][m - 1]);
	}

}

解法二

package provincialGames_11_2020_1_CC;

import java.util.Scanner;

public class _08_走方格2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[][] grid = new int[n][m];
		for (int i = 0; i < n; i++) {
			grid[i][0] = 1;
		}
		for (int i = 0; i < m; i++) {
			grid[0][i] = 1;
		}
		for (int i = 1; i < n; i++) {
			for (int j = 1; j < m; j++) {
				if (i % 2 == 1 && j % 2 == 1) {
					continue;
				}
				grid[i][j] = grid[i - 1][j] + grid[i][j - 1];
			}
		}
		System.out.println(grid[n - 1][m - 1]);
	}

}

解法三

原文地址

package provincialGames_11_2020_1_C;

import java.util.Scanner;

public class _08_走方格3 {

	static int n, m, count = 0;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		f(1, 1);
		System.out.println(count);
	}

	private static void f(int n1, int m1) {
		if (n1 == n && m1 == m) {
			count++;
			return;
		}
		if (n1 > n || m1 > m)
			return;
		int[][] arr = { { 0, 1 }, { 1, 0 } };
		for (int i = 0; i < 2; i++) {
			int x1 = n1 + arr[i][0];
			int y1 = m1 + arr[i][1];

			if (x1 % 2 == 0 && y1 % 2 == 0)
				continue;
			f(x1, y1);
		}
		return;
	}

}

解法四:dfs

原文地址

package provincialGames_11_2020_1_CC;

import java.util.Scanner;

public class _08_走方格4 {

	static long[][] dp;

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		while (scanner.hasNext()) {
			int n = scanner.nextInt();
			int m = scanner.nextInt();
			dp = new long[n + 1][m + 1];
			for (int i = 1; i <= n; i++) {
				for (int j = 1; j <= m; j++) {
					dp[i][j] = -1;
				}
			}
			long res = dfs(1, 1, n, m);
			System.out.println(res);
		}
	}

	private static long dfs(int x, int y, int n, int m) {
		if (x <= 0 || x > n || y <= 0 || y > m || (x % 2 == 0 && y % 2 == 0)) {
			return 0;
		}
		if (dp[x][y] != -1) {
			return dp[x][y];
		}
		if (x == n && y == m) {
			return 1;
		}
		dp[x][y] = dfs(x + 1, y, n, m) + dfs(x, y + 1, n, m);
		return dp[x][y];
	}

}

九、试题 I: 整数拼接

时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分

【问题描述】

给定一个长度为 n 的数组 A1, A2, · · · , An。你可以从中选出两个数 Ai 和 Aj (i 不等于 j),然后将 Ai 和 Aj 一前一后拼成一个新的整数。例如 12 和 345 可以拼成 12345 或 34512。注意交换 Ai 和 Aj 的顺序总是被视为 2 种拼法,即便是 Ai = Aj 时。

请你计算有多少种拼法满足拼出的整数是 K 的倍数。

【输入格式】

第一行包含 2 个整数 n 和 K。

第二行包含 n 个整数 A1, A2, · · · , An。

【输出格式】

一个整数代表答案。

【样例输入】

4 2

1 2 3 4

【样例输出】

6

【评测用例规模与约定】

对于 30% 的评测用例,1 ≤ n ≤ 1000, 1 ≤ K ≤ 20, 1 ≤ Ai ≤ 10^4。

对于所有评测用例,1 ≤ n ≤ 10^5,1 ≤ K ≤ 10^5,1 ≤ Ai ≤ 10^9。

解法一:双重for循环

注意超时!!! 

package provincialGames_11_2020_1_C;

import java.util.Scanner;

public class _09_整数拼接 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int k = sc.nextInt();
		int[] array = new int[n];
		for (int i = 0; i < n; i++) {
			array[i] = sc.nextInt();
		}
		int answer = 0;
		
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				String temp = array[i] + "" + array[j];
				Integer sum = Integer.valueOf(temp);
				if (i != j && sum % k == 0) {
					answer++;
				}
			}
		}
		
		System.out.println(answer);
	}

}

解法二:二维数组

package provincialGames_11_2020_1_C;

import java.util.Scanner;

public class _09_整数拼接2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int k = sc.nextInt();
		int[] num = new int[n];
		int[][] a = new int[k][10];
		int[][] b = new int[k][10];
		//int aa=1111111111;
		int temp = 0;
		// 记录有哪些数自己和自己拼接可以为k倍
		int subtract = 0;
		for (int i = 0; i < n; i++) {
			num[i] = sc.nextInt();
			// 取余
			temp = num[i] % k;
			// 余数为temp的,并且位数为当前数字相同的
			++b[temp][getLen(num[i])];
			// 求这个数*这个数的位数
			for (int j = 1; j <= 9; j++) {
				// a[i][j]代表%k余数为i的,后面带10的j次方(因为后面的数不知道几位,所以要把1-9位都算一下)
				++a[((temp * ((int) (Math.pow(10, j)) % k)) % k)][j];
			}
			// 如果自身可以拼接,就纪录一下,最后减去自身拼接的数
			if (temp + (temp * (getLen(num[i]) % k)) % k == k) {
				subtract++;
			}
		}
		int count = 0;
		for (int i = 0; i < k; i++) {
			for (int j = 1; j <= 9; j++) {
				// (余数为i的并且要加上位数为j的数字)的数量*(余数为(k-i)%k并且数字为j位数的)得数量就是组合拼接的数量
				count += a[i][j] * b[(k - i) % k][j];
			}
		}
		System.out.println(count - subtract);
	}

	// 求num有几位
	public static int getLen(int num) {
		int len = 1;
		while (num != 0) {
			num /= 10;
			len *= 10;
		}
		return len / 10;
	}

}

十、试题 J: 网络分析

时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分

【问题描述】

小明正在做一个网络实验。

他设置了 n 台电脑,称为节点,用于收发和存储数据。

初始时,所有节点都是独立的,不存在任何连接。

小明可以通过网线将两个节点连接起来,连接后两个节点就可以互相通信了。两个节点如果存在网线连接,称为相邻。

小明有时会测试当时的网络,他会在某个节点发送一条信息,信息会发送到每个相邻的节点,之后这些节点又会转发到自己相邻的节点,直到所有直接或间接相邻的节点都收到了信息。所有发送和接收的节点都会将信息存储下来。一条信息只存储一次。

给出小明连接和测试的过程,请计算出每个节点存储信息的大小。

【输入格式】

输入的第一行包含两个整数 n, m,分别表示节点数量和操作数量。节点从 1 至 n 编号。

接下来 m 行,每行三个整数,表示一个操作。

如果操作为 1 a b,表示将节点 a 和节点 b 通过网线连接起来。当 a = b 时,表示连接了一个自环,对网络没有实质影响。

如果操作为 2 p t,表示在节点 p 上发送一条大小为 t 的信息。

【输出格式】

输出一行,包含 n 个整数,相邻整数之间用一个空格分割,依次表示进行完上述操作后节点 1 至节点 n 上存储信息的大小。

【样例输入】

4 8

1 1 2

2 1 10

2 3 5

1 4 1

2 2 2

1 1 2

1 2 4

2 2 1

【样例输出】

13 13 5 3

【评测用例规模与约定】

对于 30% 的评测用例,1 ≤ n ≤ 20,1 ≤ m ≤ 100。

对于 50% 的评测用例,1 ≤ n ≤ 100,1 ≤ m ≤ 1000。

对于 70% 的评测用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 10000。

对于所有评测用例,1 ≤ n ≤ 10000,1 ≤ m ≤ 100000,1 ≤ t ≤ 100。

package provincialGames_11_2020_1_C;

import java.util.LinkedList;
import java.util.Scanner;

public class _10_网络分析 {

	static int[] data;
	static boolean[] bool;
	static LinkedList<LinkedList<Integer>> list = new LinkedList<LinkedList<Integer>>();

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		data = new int[n + 1];
		bool = new boolean[n + 1];
		int a = 0, b = 0, c = 0;
		for (int i = 0; i <= n; i++) {
			list.add(new LinkedList<>());
		}
		for (int i = 0; i < m; i++) {
			a = sc.nextInt();
			b = sc.nextInt();
			c = sc.nextInt();
			// 网络题把他们互相联系起来
			if (a == 1) {
				list.get(b).add(c);
				list.get(c).add(b);
			} else {
				bool = new boolean[n + 1];
				dfs(b, c);
			}
		}
		for (int i = 1; i <= n; i++) {
			System.out.print(data[i] + " ");
		}
	}

	// dfs遍历每一个结点
	public static void dfs(int node, int num) {
		bool[node] = true;
		data[node] += num;
		LinkedList<Integer> templist = list.get(node);
		for (int i : templist) {
			if (!bool[i]) {
				dfs(i, num);
			}
		}
	}

}

小结

dfs、bfs

做了一上午...

求求了,看仔细点,手工计算的时候 仔细点!!!读题的时候,仔细点!!!

猜你喜欢

转载自blog.csdn.net/weixin_44949135/article/details/108232922