2018第九届蓝桥杯JavaB组省赛

第一题 第几天
2000年的1月1日,是那一年的第1天。
那么,2000年的5月4日,是那一年的第几天?

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

package 第九届;

public class _01第几天 {

	public static void main(String[] args) {
		System.out.println(31+29+31+30+4);
	}

}

第二题 方格计数
如图p1.png所示,在二维平面上有无数个1x1的小方格。

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

注意:需要提交的是一个整数,不要填写任何多余内容。
在这里插入图片描述
答案:3137548

package 第九届;

public class _02方格计数 {

	public static void main(String[] args) {
		int n = 1000*1000;
		int ans = 0;
		for(int i = 1; i <= 1000; i++) {
			for(int j = 1; j <= 1000; j++) {
				if(i*i+j*j <= n) {
					ans++;
				}
			}
		}
		System.out.println(ans*4);
	}

}

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

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

注意:需要提交的是一个很庞大的复数,不要填写任何多余内容。
解析:这道题考点:大数乘法、文件传入传出
答案:太长了就不贴出来了

package 第九届;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.math.BigInteger;

public class _03复数幂 {

	public static void main(String[] args) throws FileNotFoundException {
		PrintStream ans = new PrintStream(new FileOutputStream("ans.txt"));
		System.setOut(ans);
		BigInteger a = BigInteger.valueOf(2);
		BigInteger b = BigInteger.valueOf(3);
		BigInteger c = BigInteger.valueOf(2);
		BigInteger d = BigInteger.valueOf(3);
		
		for(int i = 0; i < 123456; i++) {
			BigInteger na = a;
			a = a.multiply(c).subtract(b.multiply(d));
			b = na.multiply(d).add(b.multiply(c));
			
		}
		System.out.println(a+(b.compareTo(BigInteger.ZERO)>0 ? "+" : "")+b+"i");
	}
}

第四题 测试次数
x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机。
各大厂商也就纷纷推出各种耐摔型手机。x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后才允许上市流通。

x星球有很多高耸入云的高塔,刚好可以用来做耐摔测试。塔的每一层高度都是一样的,与地球上稍有不同的是,他们的第一层不是地面,而是相当于我们的2楼。

如果手机从第7层扔下去没摔坏,但第8层摔坏了,则手机耐摔指数=7。
特别地,如果手机从第1层扔下去就坏了,则耐摔指数=0。
如果到了塔的最高层第n层扔没摔坏,则耐摔指数=n

为了减少测试次数,从每个厂家抽样3部手机参加测试。

某次测试的塔高为1000层,如果我们总是采用最佳策略,在最坏的运气下最多需要测试多少次才能确定手机的耐摔指数呢?

请填写这个最多测试次数。

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

这道题是
一个很经典的题,而且是谷歌的面试题,难度比较大
不会的建议去力扣上看这道题的题解 (887.鸡蛋掉落),里面的大佬已经将这道题解释的很好了
答案:19

链接:

https://leetcode-cn.com/problems/super-egg-drop/submissions/

(然后,我这道题也就懵懵懂懂的,待我常拿出来做做吧)

第五题 快速排序
以下代码可以从数组a[]中找出第k小的元素。

它使用了类似快速排序中的分治算法,期望时间复杂度是O(N)的。

请仔细阅读分析源码,填写划线部分缺失的内容。

import java.util.Random;
public class Main{
    public static int quickSelect(int a[], int l, int r, int k) {
        Random rand = new Random();
        int p = rand.nextInt(r - l + 1) + l;
        int x = a[p];
        int tmp = a[p]; a[p] = a[r]; a[r] = tmp;
        int i = l, j = r;
        while(i < j) {
                    while(i < j && a[i] < x) i++;
                    if(i < j) {
                            a[j] = a[i];
                            j--;
                    }
                    while(i < j && a[j] > x) j--;
                    if(i < j) {
                            a[i] = a[j];
                            i++;
                    }
            }
            a[i] = x;
            p = i;
            if(i - l + 1 == k) return a[i];
            if(i - l + 1 < k) return quickSelect( _________________________________ ); //填空
            else return quickSelect(a, l, i - 1, k);    
    }
    public static void main(String args[]) {
        int [] a = {1, 4, 2, 8, 5, 7};
        System.out.println(quickSelect(a, 0, 5, 4));
    }
}

答案:a,i,r,k

第六题 递增三元组
给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:

  1. 1 <= i, j, k <= N
  2. Ai < Bj < Ck

【输入格式】
第一行包含一个整数N。
第二行包含N个整数A1, A2, … AN。
第三行包含N个整数B1, B2, … BN。
第四行包含N个整数C1, C2, … CN。

对于30%的数据,1 <= N <= 100
对于60%的数据,1 <= N <= 1000
对于100%的数据,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000

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

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

【输出样例】
27

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

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
解析:
1、将A,B,C三个数组中的数从小到大排序
2、用一个数组nums存B中的每个数比A中的数大的个数
3、用for循环找C中比B大的数然后将nums数组中对应的值相加,总和就是答案
4、其中有很多小细节的处理
(自认为这个解法相当不好,写在这儿以后厉害一点儿或许就知道好办法了)

package 第九届;
import java.util.Arrays;
import java.util.Scanner;

public class _06递增三元组 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int a[] = new int[n];
		int b[] = new int[n];
		int c[] = new int[n];
		int nums[] = new int[n];
		for(int i = 0; i < n; i++) {
			a[i] = sc.nextInt();
		}
		for(int j = 0; j < n; j++) {
			b[j] = sc.nextInt();
		}
		for(int i = 0; i < n; i++) {
			c[i] = sc.nextInt();
		}
		int k = 0;
		Arrays.sort(a);
		Arrays.sort(b);
		Arrays.sort(c);
		int start = 0;
		for(int i = 0; i < n; i++) {
			if(b[0] > a[i]) {
				nums[0]++;
			}
			start = i;
			if(a[i] >= b[0]) {
				break;
			}
		}
		if(nums[0] == 0) {
			System.out.println(0);
		}
		
		for(int j = 1; j < n; j++) {			
		for(int i = start+1; i < n; i++) {
				if(b[j]>a[i] && nums[j] < n) {
					nums[j] = nums[j-1] + 1;
					start++;
				}else {
					nums[j] = nums[j-1];
					break;
				}
			}
			if(nums[j-1] == n) {
				nums[j] = n;
			}
		}
		//准备c
		int ans = 0;
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < n; j++) {
				if(b[j] < c[i]) {
					ans += nums[j];
				}else {
					System.out.println(ans);
					return;
				}
			}
		}
		System.out.println(ans);
	}

}

第七题 螺旋折线
如图p1.pgn所示的螺旋折线经过平面上所有整点恰好一次。
对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。

例如dis(0, 1)=3, dis(-2, -1)=9

给出整点坐标(X, Y),你能计算出dis(X, Y)吗?

【输入格式】
X和Y

对于40%的数据,-1000 <= X, Y <= 1000
对于70%的数据,-100000 <= X, Y <= 100000
对于100%的数据, -1000000000 <= X, Y <= 1000000000

【输出格式】
输出dis(X, Y)

【输入样例】
0 1

【输出样例】
3

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

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

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
在这里插入图片描述
解析:找规律出来的,然而数字太大了会出错

package 第九届;

import java.util.Scanner;

public class _07螺旋折线 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int x = Math.abs(sc.nextInt());
		int y = Math.abs(sc.nextInt());
		int l = 0;//存x的条数
		int h = 0;//存y的条数
		int i = 1;
		int j = 1;
		int m = 0;
		if(x <= 1) {
			l = x*3;
		}else {
			while(i < x){
				
				l += i;
				i++;
			}
			l = x+l*4;
			System.out.println(l);
		}
		if(y <= 1) {
			h = y*3;
		}else {
			while(j <= y ) {
				h += j;
				j++;
			}
			h = h*4 - y;
			System.out.println(h);
		}
		
		System.out.println((l + h));
	}

}

第八题 日志统计
小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:

ts id

表示在ts时刻编号id的帖子收到一个"赞"。

现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。

具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。

给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。

【输入格式】
第一行包含三个整数N、D和K。
以下N行每行一条日志,包含两个整数ts和id。

对于50%的数据,1 <= K <= N <= 1000
对于100%的数据,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000

【输出格式】
按从小到大的顺序输出热帖id。每个id一行。

【输入样例】
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3

【输出样例】
1
3

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

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

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
解析:
题上信息要点:
1)任意一个长度为D的时间段内:也就是说当记录了第一个点赞的时间,下一个点赞超过了D时间区域,并且没有达到K个订单,则重新将此时的订单记为1,如果在D时间限度内,则继续累加,判断是否达到K个点赞
2)时间区域是左闭右开:上一个时间和当前点赞的时间差不能大于等于D

做题步骤
1、将ts,id分别存到各自的数组中
2、将ts按照从小到大排序,(注意ts和id是相对应的,所以如果ts交换,则id也要交换)
3、遍历,判断当前时间是否有id,有则将次id对应的次数++(次数的记录存入到一个数组中,下标是当前id),并且要记录当前的时间
4、当在次遍历到此数的时候,比较与上次点赞的时间差,如果满足就次数++,并判断是否达到K,如果达到则加入答案List集合,如果超出时间区域,则将当前id次数记录重置为1
5、遍历List集合,注意要每个id一行

(数据太少了,并不能保证全对,以前写过但是看以前的代码看不懂了,就又重新想了一遍,感觉比上一次做复杂了,先就这样吧)

package 第九届;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class _08日志统计 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();//组数
		int D = sc.nextInt();//时间区域
		int K = sc.nextInt();//次数
		//开辟ts,id数组
		int []ts = new int[100000];
		int []id = new int[100000];
		//1、将ts,id分别存到各自的数组中
		for(int i = 0; i < N; i++) {
			ts[i] = sc.nextInt();
			id[i] = sc.nextInt();
		}
		//2、将ts按照从小到大排序(注意ts和id是相对应的,所以如果ts交换,则id也要交换)
		for(int i = 0; i < N-1; i++) {
			for(int j = i+1; j < N; j++) {
				if(ts[i] > ts[j]) {
					int t = ts[i];
					ts[i] = ts[j];
					ts[j] = t;
					
					t = id[i];
					id[i] = id[j];
					id[j] = t;
				}
			}
		}
		//3、遍历+判断,如何找到上一次出现的时间?用memo数组存
		int count[] = new int[100000];
		int memo[] = new int[100000];
		Set<Integer> ans = new HashSet<>();//存符号条件的id
		for(int i = 0; i < N; i++) {
			if(count[id[i]] == 0) {//第一次出现
				count[id[i]]++;
				memo[count[id[i]]] = ts[i];
			}else {//不是第一次出现
				if(ts[i]-memo[count[id[i]]] < D) {
					count[id[i]]++;
					memo[count[id[i]]] = ts[i];
					if(count[id[i]] >= K) {
						ans.add(id[i]);
					}else {
						count[id[i]] = 1;
						memo[count[id[i]]] = ts[i];
					}
				}
				
			}
		}
		//输出
		for (Integer e : ans) {
			System.out.println(e);
		}
	}

}

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


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

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

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

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





…#…

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

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

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

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

【输入样例】
7

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

【输出样例】
1

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

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

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

思路:(鄙人在做的时候的思路,菜鸡思路,我发现做题时把自己的思路和自己想的解题过程写下来是个非常好的办法,不仅有助于解题,之后再复习的时候,也能快速回想起来当时自己做这题的思路和解法)

题目分析:
1)["上下左右"四个方向上连在一起的一片陆地组成一座岛屿],所以要先dfs找到岛屿数量?
2)[陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没],用dfs?
3)[依照科学家的预测,照片中有多少岛屿会被完全淹没。],再找剩多少个岛屿,又用dfs?然后与最初相减

过程
1、将地图输入进一个char[][]
2、找初始岛屿数:遍历+dfs,找到一个岛屿就进行dfs,然后还有标记,还要有一个变量来记录初始岛屿数
3、淹没:用bfs吧,层层淹没(试试),淹没一个就加入queue,然后下一份继续淹没?
4、找剩余的岛屿数:再步骤2中的方式找岛屿
5、步骤2和步骤4得到的值相减
(问号是并不确定是不是该这样做,然后在做题时会有相应的变化,老样子案例太少了,并不能保证全部都能正确)

package 第九届;

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

public class _09全球变暖 {
	static int start = 0;
	static int vis1[][] = new int[1005][1005];
	static int vis3[][] = new int[1005][1005];
	static int dir[][] = {{0,1},{0,-1},{1,0},{-1,0}};
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		sc.nextLine();
		char map[][] = new char[1005][1005];
		//1、输入地图
		for(int i = 0; i < N; i++) {
			String tem = sc.nextLine();
			map[i] = tem.toCharArray();
		}
		//2、找初始时的岛屿数
		for(int i = 0; i < N; i++) {
			for(int j = 0; j < N; j++) {
				if(map[i][j] == '#' && vis1[i][j] == 0) {
					dfs1(map,N,i,j);
					start++;
				}
			}
		}
		
		//3、淹没,题上的意思是淹没一圈的意思?
		Queue<Integer> queue = new LinkedList<Integer>();
		int vis2[][] = new int[N][N];
		for(int i = 0; i < N; i++) {
			for(int j = 0; j < N; j++) {
				if(map[i][j] == '.') {
					queue.add(i*N+j);
				}
			}
		}
		while(!queue.isEmpty()) {
			int nsize = queue.size();
			for(int i = 0; i < nsize; i++) {
				int val = queue.poll();
				int x = val/N;
				int y = val%N;
				for(int j = 0; j < 4; j++) {
					int nx = x + dir[j][0];
					int ny = y + dir[j][1];
					if(check(nx,ny,N) && vis2[x][y] == 0 && map[nx][ny] =='#') {
						map[nx][ny] = '.';//淹没
						vis2[nx][ny] = 1;
						queue.add(nx*N+ny);
					}
				}
			}
		}
		//3、找最后剩余的岛屿数量
		int end = 0;
		vis1 = new int[1005][1005];
		for(int i = 0; i < N; i++) {
			for(int j = 0; j < N; j++) {
				if(map[i][j] == '#' && vis1[i][j] == 0) {
					dfs1(map,N,i,j);
					end++;
				}
			}
		}
		
		//最后
		System.out.println(start);
		System.out.println(end);
		int ans = start-end;
		System.out.println(ans);
	}
	
	private static void dfs1(char[][] map, int N, int x, int y) {
		vis1[x][y] = 1;
		for(int i = 0; i < 4; i++) {
			int nx = x + dir[i][0];
			int ny = y + dir[i][1];
			if(check(nx,ny,N) && vis1[nx][ny] == 0 && map[nx][ny] == '#') {
				dfs1(map,N,nx,ny);
			}
		}
	}
	private static boolean check(int nx,int ny,int N) {
		if(nx >= 0 && nx < N && ny >= 0 && ny < N) {
			return true;
		}
		return false;
	}

}

第十题 堆的计数
我们知道包含N个元素的堆可以看成是一棵包含N个节点的完全二叉树。
每个节点有一个权值。对于小根堆来说,父节点的权值一定小于其子节点的权值。

假设N个节点的权值分别是1~N,你能求出一共有多少种不同的小根堆吗?

例如对于N=4有如下3种:

1

/
2 3
/
4

1

/
3 2
/
4

1

/
2 4
/
3

由于数量可能超过整型范围,你只需要输出结果除以1000000009的余数。

【输入格式】
一个整数N。
对于40%的数据,1 <= N <= 1000
对于70%的数据,1 <= N <= 10000
对于100%的数据,1 <= N <= 100000

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

【输入样例】
4

【输出样例】
3

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值