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

蓝桥杯历年真题及解析.

A:分数(难度:★)

题目:

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

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

分析:

分析题意可知,分子为2的20次方-1,分母为2的19次方。
pow计算直接输出即可。
答案=1048575/524288

代码:

满分

public class A分数 {
    public static void main(String[] args) {
        System.out.println((long)(Math.pow(2, 20)-1)+"/"+(long)Math.pow(2, 19));
    }
}

B:星期一(难度:★)

题目:

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

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

分析:

计算一下1901.1.1~2000.12.31间有多少天,除以七为整周数,再看一下余数是否凑成1,直接输出即可。
答案=5217

代码:

满分

public class B星期一 {
    static int day(int y){
        return (y%4==0&&y%100!=0||y%400==0)?366:365;
    }
    public static void main(String[] args) {
        int sum=0;
        for(int i=1901;i<2001;i++){
            sum+=day(i);
        }
        System.out.println(sum/7);
    }
}

C:复数幂(难度:★★★)

题目:

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

答案写成 “实部±虚部i” 的形式,实部和虚部都是整数(不能用科学计数法表示),中间任何地方都不加空格,实部为正时前面不加正号。(2+3i)^2 写成: -5+12i,
(2+3i)^5 的写成: 122-597i

注意:需要提交的是一个很庞大的复数,不要填写任何多余内容。

分析:

JAVA大数运算模拟复数乘法即可
答案太大放不下,建议直接运行代码到txt文件

代码:

满分

import java.io.FileWriter;
import java.io.IOException;
import java.math.*;
import java.util.*;
 
public class C复数幂 {
    public static void main(String[] args){
        BigInteger a=new BigInteger("2");
        BigInteger b=new BigInteger("3");
        BigInteger c=new BigInteger("2");
        BigInteger d=new BigInteger("3");
        for(int i=2;i<=123456;i++){
            BigInteger t=a;
            a=a.multiply(c).subtract(b.multiply(d));
            b=t.multiply(d).add(b.multiply(c));
        }
        //控制台太小,打印不了,建议文件输出
//      FileWriter fw=new FileWriter("src/Step1/out.txt",true);
//      fw.write(a+(b.compareTo(BigInteger.ZERO)==1?"+":"")+b+"i");
        System.out.println(a+(b.compareTo(BigInteger.ZERO)==1?"+":"")+b+"i");
//      fw.flush();
    }
}

D:方格计数(难度:★★)

题目:

如图
在这里插入图片描述

所示,在二维平面上有无数个1x1的小方格。

我们以某个小方格的一个顶点为圆心画一个半径为 50000 的圆。
你能计算出这个圆里有多少个完整的小方格吗?

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

分析:

从圆心划分4个象限,只计算第一象限,最终结果*4即可。
累加计算1~50000所对应的值。
答案=7853781044

代码:

满分

public class D方格计数 {
    public static void main(String[] args) {
        long ans=0,i=50000,j=1;
        for(;i>0;i--){
            for(;j<=50000;j++){
                if(i*i+j*j>50000*(long)50000){
                    ans+=(j-1);
                    break;
                }
            }
        }
        System.out.println(ans*4);
    }
}

E:打印图形(难度:★★)

题目:

如下的程序会在控制台绘制分形图(就是整体与局部自相似的图形)。

当n=1,2,3的时候,输出如下:
请仔细分析程序,并填写划线部分缺少的代码。

n=1时:
在这里插入图片描述

n=2时:
在这里插入图片描述

n=3时:
在这里插入图片描述

源程序:

public class Main
{
	static void show(byte[][] buf){
		for(int i=0; i<buf.length; i++){
			for(int j=0; j<buf[i].length; j++){
				System.out.print(buf[i][j]==0? ' ' : 'o');
			}
			System.out.println();
		}
	}
	
	static void draw(byte[][] buf, int x, int y, int size){
		if(size==1){
			buf[y][x] = 1;
			return;
		}
		
		int n = ________________________ ;  // 填空
		draw(buf, x, y, n);
		draw(buf, x-n, y ,n);
		draw(buf, x+n, y ,n);
		draw(buf, x, y-n ,n);
		draw(buf, x, y+n ,n);
	}
	
	public static void main(String[] args){
		final int N = 3;
		int t = 1;
		for(int i=0; i<N; i++) t *= 3;
		
		byte[][] buf = new byte[t][t];
		draw(buf, t/2, t/2, t);
		show(buf);
	}
}

分析:

观察发现,主函数内有 t * 3 多次,所以推测 size / 3;
验证后正确。
答案=size/3

代码:

满分

public class E打印图形
{
	static void show(byte[][] buf){
		for(int i=0; i<buf.length; i++){
			for(int j=0; j<buf[i].length; j++){
				System.out.print(buf[i][j]==0? ' ' : 'o');
			}
			System.out.println();
		}
	}
	
	static void draw(byte[][] buf, int x, int y, int size){
		if(size==1){
			buf[y][x] = 1;
			return;
		}
		
		int n = size/3;//________________________ ;  // 填空
		draw(buf, x, y, n);
		draw(buf, x-n, y ,n);
		draw(buf, x+n, y ,n);
		draw(buf, x, y-n ,n);
		draw(buf, x, y+n ,n);
	}
	
	public static void main(String[] args){
		final int N = 3;
		int t = 1;
		for(int i=0; i<N; i++) t *= 3;
		
		byte[][] buf = new byte[t][t];
		draw(buf, t/2, t/2, t);
		show(buf);
	}
}

F:航班时间(难度:★★★)

题目:

【问题背景】
小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: m: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小时。

分析:

字符串处理问题,处理过程比较复杂,但不是很难,
细心搞一搞没问题。

后期再考虑优化一下代码。

代码:

在这里插入图片描述

import java.util.*;
 
public class F航班时间 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int t=sc.nextInt();
        sc.nextLine();
        int val[]={60*60,60,1};
        while(t-->0){
            String to=sc.nextLine();
            String qd_to[]=to.split(" ");
            String to_qf[]=qd_to[0].split(":");
            String to_dd[]=qd_to[1].split(":");
            int t1_qf=Integer.valueOf(to_qf[0])*val[0]+Integer.valueOf(to_qf[1])*val[1]+Integer.valueOf(to_qf[2])*val[2];
            int t1_dd=Integer.valueOf(to_dd[0])*val[0]+Integer.valueOf(to_dd[1])*val[1]+Integer.valueOf(to_dd[2])*val[2];
            int t1=t1_dd-t1_qf;
            if(qd_to.length==3){
                t1+=Integer.valueOf(qd_to[2].substring(2, 3))*24*60*60;
            }
            String come=sc.nextLine();
            String qd_come[]=come.split(" ");
            String come_qf[]=qd_come[0].split(":");
            String come_dd[]=qd_come[1].split(":");
            int t2_qf=Integer.valueOf(come_qf[0])*val[0]+Integer.valueOf(come_qf[1])*val[1]+Integer.valueOf(come_qf[2])*val[2];
            int t2_dd=Integer.valueOf(come_dd[0])*val[0]+Integer.valueOf(come_dd[1])*val[1]+Integer.valueOf(come_dd[2])*val[2];
            int t2=t2_dd-t2_qf;
            if(qd_come.length==3){
                t2+=Integer.valueOf(qd_come[2].substring(2, 3))*24*60*60;
            }
            int time=(t1+t2)/2;
             
            int dd=time/(24*60*60),hh=(time%(24*60*60))/(60*60),mm=(time%(60*60))/60,ss=time%60;
            System.out.println((hh<10?"0"+hh:hh)+":"+(mm<10?"0"+mm:mm)+":"+(ss<10?"0"+ss:ss)+(dd!=0?" (+"+dd+")":""));
             
        }
    }
 
}

G:三体攻击(难度:★★★★)

题目:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分析:

//稍等

代码:

//稍等

H:全球变暖(难度:★★★★)

题目:

你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:

.......
.##....
.##....
....##.
..####.
...###.
.......

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

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

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

.......
.......
.......
.......
....#..
.......
.......

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

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

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

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

【输入样例】

7 
.......
.##....
.##....
....##.
..####.
...###.
.......  

【输出样例】

1

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

分析:

这是一个DFS题目,我们录入数据后首先搜索查一下陆地的岛屿数目。
与此同时我们给每一个岛屿进行编号,当我们发现有某个岛屿无法被淹没时加入HashSet。
最终岛屿数减去hashset内的岛屿数量即被淹没的所有岛屿的数量。

代码:

在这里插入图片描述

import java.util.*;

public class H全球变暖 {
//  public static String[] strArray = new String[1010];
    public static char[][] ca = new char[1010][1010];
    public static int n;
    public static int[] dx = { -1, 1, 0, 0 };
    public static int[] dy = { 0, 0, -1, 1 };
    public static int[][] overWhelm = new int[1010][1010];// 判断该陆地是否会被淹没,1表示会被淹没,大于1的数表示剩下的小岛
    public static int[][] v = new int[1010][1010];// 判断该陆地是否已经搜索过
    public static long num = 0;// 所有小岛数
    public static Queue<Node> que = new LinkedList<>();
 
    public static void BFS() {
//      for (int i = 0; i < n; i++) {
//          ca[i] = strArray[i].toCharArray();
//      }
        int d_num = 2;// 用来表示不同的小岛
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (ca[i][j] == '#' && v[i][j] == 0) {
                    Node node = new Node(i, j);
                    que.add(node);
                    v[i][j] = 1;
                    while (!que.isEmpty()) {
                        Node tempNode = que.remove();
                        check(tempNode.coordX, tempNode.coordY, d_num);
                        for (int k = 0; k < 4; k++) {
                            int tempx = tempNode.coordX + dx[k];
                            int tempy = tempNode.coordY + dy[k];
                            if (tempx >= 0 && tempy >= 0 && tempx < n && tempy < n) {
                                if (ca[tempx][tempy] == '.') {// 上下左右存在海洋,会被淹没
                                    continue;
                                }
                                if (ca[tempx][tempy] == '#' && v[tempx][tempy] == 0) {
                                    que.add(new Node(tempx, tempy));
                                    v[tempx][tempy] = 1;
                                }
                            }
                        }
 
                    }
                    num++;
                    d_num++;
                }
            }
        }
    }
 
    // 判断上下左右是否有海洋
    public static void check(int tempx, int tempy, int d_num) {
        for (int k = 0; k < 4; k++) {
            int tax = tempx + dx[k];
            int tay = tempy + dy[k];
            // 边界之外全是海洋
            if (tax < 0 || tay < 0 || tax >= n || tay >= n) {
                overWhelm[tempx][tempy] = 1;
                break;
            }
            if (ca[tax][tay] == '.') {
                overWhelm[tempx][tempy] = 1;
                break;
            }
            overWhelm[tempx][tempy] = d_num;
        }
    }
 
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        for (int i = 0; i < n; i++)
//          strArray[i] = in.next();
            ca[i]=in.next().toCharArray();
        BFS();// 广搜
        Set<Integer> set = new HashSet<>();// 存放的是未被淹没的小岛
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (overWhelm[i][j] > 1)
                    set.add(overWhelm[i][j]);
        System.out.println(num - (long) set.size());
    }
    static class Node {
        int coordX;
        int coordY;
         
        Node(int x, int y) {
            coordX = x;
            coordY = y;
        }
    }
}
 

I:倍数问题(难度:★★★★★)

题目:

【题目描述】
众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 n 个数,希望你从这 n 个数中找到三个数,使得这三个数的和是 K 的倍数,且这个和最大。数据保证一定有解。
【输入格式】
从标准输入读入数据。
第一行包括 2 个正整数 n, K。
第二行 n 个正整数,代表给定的 n 个数。

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

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

【样例输出】
9

【样例解释】
选择2、3、4。
在这里插入图片描述

分析:

//稍等

代码:

//稍等

J:付账问题(难度:★★★★★)

题目:

【题目描述】
几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。

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

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

标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的“偏差有多大”。形式化地说,设第 i 个人付的钱为 bi 元,那么标准差为 :
在这里插入图片描述
【输入格式】
从标准输入读入数据。
第一行包含两个整数 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。

分析:

//稍等

代码:

//稍等

算法交流群:

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王跃坤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值