Advertisement

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<year2;i++) {
    
 			//1.判断是不是闰年
    
 			if((i%4==0&&i%100!=0) || i%400==0) {//是闰年,有356天
    
 				ans += 366;
    
 			}else {
    
 				ans += 365;
    
 			}
    
 		
    
 		}
    
 		
    
 	//2.计算月
    
 	int[] Mday= {0,31,28,31,30,31,30,31,31,30,31,30,31};
    
 	for(int i=1;i<month1;i++) {
    
 		if(i==2 && f1(year1)) {
    
 			ans -= 29;
    
 		}else {
    
 			ans -= Mday[i];
    
 		}
    
 	}
    
 	
    
 	for(int i=1;i<month2;i++) {
    
 		if(i==2 && f1(year2)) {
    
 			ans += 29;
    
 		}else {
    
 			ans += Mday[i];
    
 		}
    
 	}
    
 	
    
 	//3.算日期
    
 	ans -= day1;
    
 	ans += day2;
    
 	
    
 	return ans;
    
 	
    
 	}
    
  
    
 	static boolean f1(int i) {
    
 		if((i%4==0&&i%100!=0) || i%400==0)return true;
    
 		else return false;
    
 	}
    
 }

第三题:复数幂
题目描述
设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 的圆。
你能计算出这个圆里有多少个完整的小方格吗?
注意:需要提交的是一个整数,不要填写任何多余内容。

解析: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<d.length;i++) {
    
 			for(int j=1;j<d[i].length;j++) {
    
 				for(int k=1;k<d[i][j].length;k++) {
    
 					d[i][j][k] = input.nextInt();
    
 				}
    
 			}
    
 		}
    
 		//3.接收每一轮的攻击
    
 		ArrayList<Integer>[] list = new ArrayList[m];
    
 		for(int i=0;i<m;i++) {
    
 			list[i] = new ArrayList<>();
    
 			for(int j=0;j<7;j++) {
    
 				list[i].add(input.nextInt());
    
 			}
    
 		}
    
 		
    
 		//4.模拟攻击战舰
    
 		int ans = 0;
    
 		boolean boo = false;
    
 		for(int i=0;i<m;i++) {//m次攻击
    
 			ans++;
    
 			int lat = list[i].get(0);
    
 			int rat = list[i].get(1);
    
 			int lbt = list[i].get(2);
    
 			int rbt = list[i].get(3);
    
 			int lct = list[i].get(4);
    
 			int rct = list[i].get(5);
    
 			int ht = list[i].get(6);
    
 			
    
 			for(int l=lat;l<=rat;l++) {
    
 				for(int j=lbt;j<=rbt;j++) {
    
 					for(int k=lct;k<=rct;k++) {
    
 						d[l][j][k] -= ht;
    
 						if(d[l][j][k] < 0) boo=true;
    
 					}
    
 					if(boo) break;
    
 				}
    
 				if(boo) break;
    
 			}
    
 			if(boo) break;
    
 		}
    
 		
    
 		System.out.println(ans);
    
 	}
    
  
    
 }

第八题:全球变暖
题目描述
你有一张某海域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<n;i++) {
    
 			String s = input.nextLine();
    
 			for(int j=0;j<n;j++) {
    
 				island[i][j] = s.charAt(j);
    
 			}
    
 		}
    
 		
    
 		//2.用户输入完成
    
 		int ans1 = 0;//表示被淹没岛屿的数量
    
 		int ans2 = 0;//表示所有岛屿的数量
    
 		for(int i=0;i<n;i++) {
    
 			for(int j=0;j<n;j++) {
    
 				if(island[i][j] == '#') {
    
 					ans2++;
    
 					if(BFS(i,j,island)) {
    
 						ans1++;
    
 					}
    
 				}
    
 			
    
 			}
    
 		}
    
 //		System.out.println(ans2);
    
 //		System.out.println(ans1);
    
 		System.out.println(ans2 - ans1);
    
 	}
    
 	
    
 	static boolean BFS(int x,int y,char[][] island) {
    
 		Queue<stat> 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。

资源约定:
峰值内存消耗(含虚拟机) < 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<N.length;i++) {
    
 			N[i] = input.nextInt();
    
 		}
    
 		
    
 		//2.用户输入完成
    
 		Arrays.sort(N);
    
  
    
 		double avg = (sum*1.0) / n;//支付钱的平均值
    
 		double ans = 0;//
    
 		for(int i=0;i<N.length;i++) {//遍历每个用户需要支付多少钱
    
 			if(N[i]*(n-i) < S) {//所带的钱不够,支付当前自己所有的钱
    
 				ans += Math.pow(N[i] - avg, 2);
    
 				S -= N[i];
    
 			}else {//所带的钱够,支付平均值
    
 				ans += (n-i)*Math.pow((S*1.0)/(n-i) -avg, 2);
    
 				break;//跳出循环
    
 			}	
    
 		}
    
 		
    
 		
    
 		ans = Math.pow(ans/n, 1.0/2);
    
 		//4.输出答案,保留四位小数
    
 		System.out.printf("%.4f",ans);
    
 		
    
 		
    
 		
    
 	}
    
 }

全部评论 (0)

还没有任何评论哟~