2018年第九届蓝桥杯省赛Java A组真题解析(带源码)

第一题:分数
题目描述
1/1 + 1/2 + 1/4 + 1/8 + 1/16 + …
每项是前一项的一半,如果一共有20项,
求这个和是多少,结果用分数表示出来。
类似:
3/2
当然,这只是加了前2项而已。分子分母要求互质。

注意:
需要提交的是已经约分过的分数,中间任何位置不能含有空格。
请不要填写任何多余的文字或符号。


分析:数学问题,将所有分数都化为成第20项的分母,然后所有分子相加,最后分子和分母化简,输出最后化简的分子和分母即可

package A组2018年;
//答案1048575/524288

public class _1分数 {
	public static void main(String[] args) {
		int a=0;
		int b=0;
		// a/b
		for(int i=0;i<20;i++) {
			a += (int)Math.pow(2, i);
		}
		b = (int)Math.pow(2, 19);
		
//		System.out.println(a+" " + b+" "+gcd(a,b));
//		int i =2;
//		while(i<10) {
//			if(a%i==0 && b%i==0) {
//				a /= i;
//				b /= i;
//			}else {
//				i++;
//			}
//		}
//		System.out.println(a+" " + b+" "+gcd(a,b));
		
		System.out.println(a+"/" + b);
	}
	
	static int gcd(int a,int b) {
		if(b==0)return a;
		else return gcd(b,a%b);
	}

}

第二题:星期一

题目描述
整个20世纪(1901年1月1日至2000年12月31日之间),一共有多少个星期一?
(不要告诉我你不知道今天是星期几)

注意:需要提交的只是一个整数,不要填写任何多余的内容或说明文字。

解析:1.首先计算出19011月1日至2000年12月31日之间有几天,然后除以7,有几个周就有几个周一

2.利用今天是周几判断出1901年1月1日和2000年12月31日分别是周几,假如其中一个是周一的话,周一数量加一

package A组2018年;


//答案5217
//正确

public class _2星期一 {
	public static void main(String[] args) {
		//2022.3.31周四
		//2022.3.28周一
		//31 - 28 = 3
		
		//1.计算1901.1.1 到2022.3.28有几天
		//推算出那天是周几
//		System.out.println(chack(20220304,20220331));
//		System.out.println(chack(20220304,20220331)/7);
		//今天周四  余数为2
//		0301周二
//		0304余数6  往前退6天周五
		
//		1901年1月1日至2000年12月31日之间
//		System.out.println(chack(20200101,20220331));//729  365 +364
//		System.out.println(chack(20200101,20220331)%7);
		
		//2021年1月1日周五
//		2020年1月1日周三
		
//		System.out.println(chack(19010101,20220331));//729  365 +364
//		System.out.println(chack(19010101,20220331)%7);
//		19010101周二
		
//		2000年12月31日之
//		System.out.println(chack(20001231,20220331));//729  365 +364
//		System.out.println(chack(20001231,20220331)%7);
//		20001231周天
		
		System.out.println(chack(19010101,20001231)/7);
//		其中有5217个周一
		
	}
	
	static int chack(int a,int b) {//19010101 20220328
		int ans = 0;
		int year1 = a/10000;
		int year2 = b/10000;
		int month1 = ((a/100)%100);
		int month2 = ((b/100)%100);
		int day1 = a%100;
		int day2 = b%100;
		
		for(int i = year1;i

第三题:复数幂
题目描述
设i为虚数单位。对于任意正整数n,(2+3i)^n 的实部和虚部都是整数。
求 (2+3i)^123456 等于多少? 即(2+3i)的123456次幂,这个数字很大,要求精确表示。

答案写成 “实部±虚部i” 的形式,实部和虚部都是整数(不能用科学计数法表示),中间任何地方都不加空格,实部为正时前面不加正号。(2+3i)^2 写成: -5+12i,
(2+3i)^5 的写成: 122-597i
解析:1.公式:(a+bi)(c+di)=ac+adi+bci-bd=(ac-bd)+(ad+bc)i

2.填空题利用Java大数暴力

3.eclipse控制台输出不了这么大的数,用idea能输出

package B站.A组2018;

import java.math.BigInteger;

/*题目描述
        设i为虚数单位。对于任意正整数n,(2+3i)^n 的实部和虚部都是整数。
        求 (2+3i)^123456 等于多少? 即(2+3i)的123456次幂,这个数字很大,要求精确表示。
        答案写成 “实部±虚部i” 的形式,实部和虚部都是整数(不能用科学计数法表示),
        中间任何地方都不加空格,实部为正时前面不加正号。
        (2+3i)^2 写成: -5+12i,
        (2+3i)^5 的写成: 122-597i
        */
//负数中i*i=-1
//思路:有公式(A+Bi)*(a+bi)=Aa+Abi+Bia+Bibi=Aa+Abi+Bia-Bb=(Aa-Bb)+(Ab+Ba)i
//大数运算
public class _3复数幂 {

    public static void main(String[] args) {
        BigInteger a= BigInteger.valueOf(2);
        BigInteger b= BigInteger.valueOf(3);
        for (int i = 1; i < 123456; i++) {
            BigInteger a1=a;
            BigInteger b1=b;
            a = a1.multiply(BigInteger.valueOf(2)).subtract(b1.multiply(BigInteger.valueOf(3))) ;
            b = b1.multiply(BigInteger.valueOf(2)).add(a1.multiply(BigInteger.valueOf(3))) ;
        }
        System.out.print(a);
        System.out.print(b+"i");
//        if (b > 0) System.out.print("+"+b+"i");
//        else System.out.print(b+"i");
    }
}

第四题:方格计数

题目描述
如图p1.png所示,在二维平面上有无数个1x1的小方格。
我们以某个小方格的一个顶点为圆心画一个半径为 50000 的圆。
你能计算出这个圆里有多少个完整的小方格吗?
注意:需要提交的是一个整数,不要填写任何多余内容。

2018年第九届蓝桥杯省赛Java A组真题解析(带源码)_第1张图片

 解析:1.寻找方块右上角的点,计算它到圆心的距离

 2.计算1/4的圆就可以知道整个圆

3.最后数值很大,用long

package A组2018年;
//思路:寻找方块右上角的点,计算它到圆心的距离
//计算1/4的圆就可以知道整个圆
public class _4方格计数 {
	public static void main(String[] args) {
//		int[][] num = new int[50000][50000];
		long ans = 0;
		for(int i=1;i<=50000;i++) {
			for(int j=1;j<=50000;j++) {
				if(chack(i,j)) {
					ans++;
				}
			}
		}
//		7853781044
		System.out.println(ans*4);
	}
	
	static Boolean chack(int x,int y) {
		if(Math.pow(x,2) + Math.pow(y,2)  >  Math.pow(50000,2)) {
			return false;
		}else {
			return true;
		}
	} 
}

第六题:航班时间
题目描述
小h前往美国参加了蓝桥杯国际赛。小h的女朋友发现小h上午十点出发,上午十二点到达美国,于是感叹到“现在飞机飞得真快,两小时就能到美国了”。

小h对超音速飞行感到十分恐惧。仔细观察后发现飞机的起降时间都是当地时间。由于北京和美国东部有12小时时差,故飞机总共需要14小时的飞行时间。

不久后小h的女朋友去中东交换。小h并不知道中东与北京的时差。但是小h得到了女朋友来回航班的起降时间。小h想知道女朋友的航班飞行时间是多少。

【问题描述】
对于一个可能跨时区的航班,给定来回程的起降时间。假设飞机来回飞行时间相同,求飞机的飞行时间。

【输入格式】
从标准输入读入数据。

一个输入包含多组数据。

输入第一行为一个正整数T,表示输入数据组数。

每组数据包含两行,第一行为去程的 起降 时间,第二行为回程的 起降 时间。

起降时间的格式如下

h1:m1:s1 h2:m2:s2

h1:m1:s1 h3:m3:s3 (+1)

h1:m1:s1 h4:m4:s4 (+2)
表示该航班在当地时间h1时m1分s1秒起飞,

第一种格式表示在当地时间 当日 h2时m2分s2秒降落

第二种格式表示在当地时间 次日 h3时m3分s3秒降落。

第三种格式表示在当地时间 第三天 h4时m4分s4秒降落。

对于此题目中的所有以 hⓂ️s 形式给出的时间, 保证 ( 0<=h<=23, 0<=m,s<=59 ).

【输出格式】
输出到标准输出。

对于每一组数据输出一行一个时间hh:mm:ss,表示飞行时间为hh小时mm分ss秒。

注意,当时间为一位数时,要补齐前导零。如三小时四分五秒应写为03:04:05。

【样例输入】
3
17:48:19 21:57:24
11:05:18 15:14:23
17:21:07 00:31:46 (+1)
23:02:41 16:13:20 (+1)
10:19:19 20:41:24
22:19:04 16:41:09 (+1)

【样例输出】
04:09:05
12:10:39
14:22:05

【限制与约定】
保证输入时间合法,飞行时间不超过24小时。

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

解析:无
 

第七题:三体攻击
题目描述
三体人将对地球发起攻击。为了抵御攻击,地球人派出了 A × B × C 艘战舰,在太空中排成一个 A 层 B 行 C 列的立方体。其中,第 i 层第 j 行第 k 列的战舰(记为战舰 (i, j, k))的生命值为 d(i, j, k)。

三体人将会对地球发起 m 轮“立方体攻击”,每次攻击会对一个小立方体中的所有战舰都造成相同的伤害。具体地,第 t 轮攻击用 7 个参数 lat, rat, lbt, rbt, lct, rct, ht 描述;
所有满足 i ∈ [lat, rat],j ∈ [lbt, rbt],k ∈ [lct, rct] 的战舰 (i, j, k) 会受到 ht 的伤害。如果一个战舰累计受到的总伤害超过其防御力,那么这个战舰会爆炸。

地球指挥官希望你能告诉他,第一艘爆炸的战舰是在哪一轮攻击后爆炸的。

【输入格式】
从标准输入读入数据。
第一行包括 4 个正整数 A, B, C, m;
第二行包含 A × B × C 个整数,其中第 ((i − 1)×B + (j − 1)) × C + (k − 1)+1 个数为 d(i, j, k);
第 3 到第 m + 2 行中,第 (t − 2) 行包含 7 个正整数 lat, rat, lbt, rbt, lct, rct, ht。

【输出格式】
输出到标准输出。
输出第一个爆炸的战舰是在哪一轮攻击后爆炸的。保证一定存在这样的战舰。

【样例输入】
2 2 2 3
1 1 1 1 1 1 1 1
1 2 1 2 1 1 1
1 1 1 2 1 2 1
1 1 1 1 1 1 2

【样例输出】
2

【样例解释】
在第 2 轮攻击后,战舰 (1,1,1) 总共受到了 2 点伤害,超出其防御力导致爆炸。

【数据约定】
对于 10% 的数据,B = C = 1;
对于 20% 的数据,C = 1;
对于 40% 的数据,A × B × C, m ≤ 10, 000;
对于 70% 的数据,A, B, C ≤ 200;
对于所有数据,A × B × C ≤ 10^6, m ≤ 10^6, 0 ≤ d(i, j, k), ht ≤ 10^9。

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 3000ms

解析:暴力求解,在暴力的基础上剪枝

但是不能AC,最后得分66分

package A组2018年;

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

//暴力
//66分
public class _7三体攻击_剪枝优化 {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int A = input.nextInt();
		int B = input.nextInt();
		int C = input.nextInt();
		int m = input.nextInt();//m次攻击
		
		int[][][] d = new int[A+1][B+1][C+1];
		//2.接收每个战舰的生命值
		for(int i=1;i[] list = new ArrayList[m];
		for(int i=0;i();
			for(int j=0;j<7;j++) {
				list[i].add(input.nextInt());
			}
		}
		
		//4.模拟攻击战舰
		int ans = 0;
		boolean boo = false;
		for(int i=0;i

第八题:全球变暖
题目描述
你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:


.##…
.##…
…##.
…####.
…###.

其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

例如上图中的海域未来会变成如下样子:





…#…

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

【输入格式】
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。

照片保证第1行、第1列、第N行、第N列的像素都是海洋。

【输出格式】
一个整数表示答案。

【输入样例】
7

.##…
.##…
…##.
…####.
…###.

【输出样例】
1

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

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

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

 

解析:1.岛屿问题——>连通块问题

2.利用BFS广度优先遍历连通块;

3.遍历小岛中的每个岛屿时,记录有多少个岛屿会被淹没,然后和小岛中岛屿总数比较,会被淹没的岛屿的数量等于小岛上所有岛屿的数量,那么说明小岛会被淹没,否则不会

package A组2018年;

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
/*
7
.......
.##....
.##....
....##.
..####.
..####.
.......
*/
public class _8全球变暖 {
	static int n;
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		n = input.nextInt();
		input.nextLine();
		char[][] island = new char[n][n];
		for(int i=0;i queue = new ArrayDeque<>();
		queue.add(new stat(x,y));
		island[x][y] = '#';
		int land = 0;//总的岛屿的数量
		int Nland = 0;//被淹没岛屿的数量
		
		while(!queue.isEmpty()) {
			stat now = queue.poll();
			land++;//时陆地就加一
			if(check(now.x,now.y,island)) {
				Nland++;
			}
			
			//遍历这个陆地的上下左右
			int[] dx = {0,1,0,-1};
			int[] dy = {1,0,-1,0};
			for(int i=0;i<4;i++) {
				int nowx = now.x + dx[i];
				int nowy = now.y + dy[i];
				if(nowx<0 || nowx>=island.length || nowy<0 || nowy>=island[0].length) {
					continue;
				}
				if(island[nowx][nowy] != '#') {
					continue;
				}
				//说明这个点是陆地
				queue.add(new stat(nowx,nowy));
				island[nowx][nowy] = '@';
			}
		}
		
//		System.out.println(land);
//		System.out.println(Nland);
		return land > Nland;//大于表示不会被淹没
		
	}
	
	static boolean check(int x,int y,char[][] island) {
		int[] dx = {0,1,0,-1};
		int[] dy = {1,0,-1,0};
		for(int i=0;i<4;i++) {
			int nowx = x + dx[i];
			int nowy = y + dy[i];
			if(nowx<0 || nowx>=island.length || nowy<0 || nowy>=island[0].length) {
				continue;
			}
			if(island[nowx][nowy] == '.') {//如果周围有海,就说明会被淹没
				return true;
			}
		}
		return false;
	}
	
	static class stat{
		int x;
		int y;
		stat(int x,int y){
			this.x = x;
			this.y = y;
		}
	}
}

第九题:倍数问题
题目描述
众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 n 个数,希望你从这 n 个数中找到三个数,使得这三个数的和是 K 的倍数,且这个和最大。数据保证一定有解。

【输入格式】
从标准输入读入数据。
第一行包括 2 个正整数 n, K。
第二行 n 个正整数,代表给定的 n 个数。

【输出格式】
输出到标准输出。
输出一行一个整数代表所求的和。

【样例输入】
4 3
1 2 3 4

【样例输出】
9

【样例解释】
选择2、3、4。

【数据约定】
对于 30% 的数据,n <= 100。
对于 60% 的数据,n <= 1000。
对于另外 20% 的数据,K <= 10。
对于 100% 的数据,1 <= n <= 10^5, 1 <= K <= 10^3,给定的 n 个数均不超过 10^8。

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

 

解析:无

第十题:付账问题
题目描述
几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。

现在有 n 个人出去吃饭,他们总共消费了 S 元。其中第 i 个人带了 ai 元。幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?

为了公平起见,我们希望在总付钱量恰好为 S 的前提下,最后每个人付的钱的标准差最小。这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是1分钱的整数倍。你需要输出最小的标准差是多少。

标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的“偏差有多大”。形式化地说,设第 i 个人付的钱为 bi 元,那么标准差为 : [参见p1.png]

【输入格式】
从标准输入读入数据。
第一行包含两个整数 n、S;
第二行包含 n 个非负整数 a1, …, an。

【输出格式】
输出到标准输出。
输出最小的标准差,四舍五入保留 4 位小数。
保证正确答案在加上或减去 10^−9 后不会导致四舍五入的结果发生变化。

【样例输入】
5 2333
666 666 666 666 666

【样例输出】
0.0000

【样例解释】
每个人都出 2333/5 元,标准差为 0。

再比如:
【样例输入】
10 30
2 1 4 7 4 8 3 6 4 7

【样例输出】
0.7928

【数据约定】
对于 10% 的数据,所有 ai 相等;
对于 30% 的数据,所有非 0 的 ai 相等;
对于 60% 的数据,n ≤ 1000;
对于 80% 的数据,n ≤ 10^5;
对于所有数据,n ≤ 5 × 10^5, 0 ≤ ai ≤ 10^9。

2018年第九届蓝桥杯省赛Java A组真题解析(带源码)_第2张图片

 

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

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

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

解析:1.求标准差最小,那就是说,所有人付的钱要尽可能的接近平均值。利用贪心的思想,每个人付的钱的数量都是当前情况下最接近平均值的;

2.首先对数组排序,从钱最少的开始,所带的钱比平均值少就全部支付,所带的钱比当前平均值多就支付当前平均值,每次支付钱之前先计算当前情况下的平均值(剩余需要支付钱/剩余人数);

3.计算没人需要支付多少钱的时候就计算方差,不然java最后会因为精度问题导致部分答案错误

package A组2018年;

import java.util.Arrays;
import java.util.Scanner;
//优化:将原本分开算的标准差在循环中就一起计算
//这样减少了精度的误差
//100分
public class _10付账问题_优化 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();//有n个人
		long S = input.nextLong();//总共消费了S元
		long[] N = new long[n];//每个人带的钱
		double sum = S;
		for(int i=0;i

你可能感兴趣的:(java,蓝桥杯)