蓝桥杯31天冲刺之二十六 [java]

板块一:之前做过的历届真题的复习

更题解可以用一两句话带过,主要记录再刷之后的心得,比如用到的知识点或者自己大意的地方

这里的题都是原来写过的,如果是自己确实掌握的话基本看了题目就知道怎么做了,完全敲完代码保持在10分钟内是比较好的,如果超过这个时间就要再细细分析一下自己是哪里还有问题

含2天数(20年国赛——3月16日)

题目链接:https://www.lanqiao.cn/problems/1038/learning/

主要还是LocalDate这个类的使用,感觉用起来比Calendar好用一点

遍历中间的所有天数,然后判断,还是同理,先判断年,再判断月日,这样可以稍微少一点计算

package daily;

import java.time.LocalDate;

/**
 * https://www.lanqiao.cn/problems/1038/learning/
 * 
 * @author Jia
 *
 */
public class day4_2_2 {
	public static void main(String[] args) {
		LocalDate left = LocalDate.of(1900, 1, 1);
		LocalDate right = LocalDate.of(9999, 12, 31);
		int ans = 0;
		while (left.compareTo(right) <= 0) {
			int year = left.getYear();
			int month = left.getMonthValue();
			int day = left.getDayOfMonth();
			if (check(year) || check(month) || check(day)) {
				ans++;
			}
			left = left.plusDays(1);
		}
		System.out.println(ans);
	}

	/**
	 * 判断这个数是不是包含2
	 * 
	 * @param num
	 * @return
	 */
	private static boolean check(int num) {
		while (num > 0) {
			if (num % 10 == 2) {
				return true;
			}
			num /= 10;
		}
		return false;
	}
}

蓝桥幼儿园(3月21日)

题目链接:https://www.lanqiao.cn/problems/1135/learning/

这个题复习并查集的知识,findunion两个方法的写法尽量背过,这里的写法是带路径压缩的(推荐使用这种),不带路径压缩的写法可以翻前面的看看

package daily;

import java.util.Scanner;

/**
 * https://www.lanqiao.cn/problems/1135/learning/
 * 
 * @author Jia
 *
 */
public class day3_2_3 {
	static int[] arr;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		int M = sc.nextInt();
		arr = new int[N + 1];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = i;
		}

		for (int i = 0; i < M; i++) {
			int op = sc.nextInt();
			int x = sc.nextInt();
			int y = sc.nextInt();
			if (op == 1) {
				union(x, y);
			} else {
				int xParent = find(x);
				int yParent = find(y);
				System.out.println(xParent == yParent ? "YES" : "NO");

			}
		}
		sc.close();
	}

	/**
	 * 查找当前节点所在集合
	 * 
	 * @param x
	 * @return
	 */
	private static int find(int x) {
		return arr[x] == x ? x : (arr[x] = find(arr[x]));
	}

	/**
	 * 将x,y的放入一个集合中
	 * 
	 * @param x
	 * @param y
	 */
	private static void union(int x, int y) {
		int xParent = find(x);
		int yParent = find(y);
		if (xParent > yParent) {
			arr[xParent] = yParent;
		} else {
			arr[yParent] = xParent;
		}
	}
}

七星填数字(16年国赛——3月27日)

题目链接:https://www.lanqiao.cn/problems/658/learning/

这个就直接回溯法列出所有的情况然后判断是否满足条件就ok了

package daily;

public class day3_27_1 {
	static int[] ans;
	static boolean flag;

	public static void main(String[] args) {
		int[] arr = { 6, 14, 11, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13 };
		backtrack(arr, 3);// 回溯找到所有排列方法
		for (int i = 3; i < 7; i++) {
			System.out.print(ans[i] + " ");
		}
	}

	private static void backtrack(int[] arr, int index) {
		if (index == arr.length) {
			check(arr);
		} else {
			for (int j = index; j < arr.length; j++) {
				if (!flag) {
					// 没有找到时候就继续找
					swap(arr, index, j);
					backtrack(arr, index + 1);
					swap(arr, index, j);
				}

			}
		}
	}

	/**
	 * 交换元素
	 * 
	 * @param arr
	 * @param i
	 * @param j
	 */
	private static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

	/**
	 * 检查七条边是否相等
	 * 
	 * @param arr
	 */
	private static void check(int[] arr) {
		int num1 = arr[3] + arr[4] + arr[5] + arr[6];
		int num2 = arr[6] + arr[8] + arr[10] + arr[13];
		int num3 = arr[13] + arr[11] + arr[9] + arr[1];
		int num4 = arr[1] + arr[7] + arr[4] + arr[0];
		int num5 = arr[0] + arr[5] + arr[8] + arr[2];
		int num6 = arr[2] + arr[10] + arr[11] + arr[12];
		int num7 = arr[12] + arr[9] + arr[7] + arr[3];
		if (num1 == num2 && num2 == num3 && num3 == num4 && num4 == num5 && num5 == num6 && num6 == num7) {
			ans = arr.clone();
			flag = false;
		}
	}
}

日志统计(18年省赛——3月13日)

题目链接:https://www.lanqiao.cn/problems/179/learning/

感觉这种模拟的做起来还是麻烦的,只能慢慢做,调细节,麻了,最后还是超时了,应该能过80%的用例

package daily;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * https://www.lanqiao.cn/problems/179/learning/
 * 
 * @author Jia
 *
 */
public class day4_2_4 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		int D = sc.nextInt();
		int K = sc.nextInt();

		// 初始化所有节点
		Map<Integer, RizhiNode> map = new HashMap<>();
		for (int i = 0; i < N; i++) {
			int ts = sc.nextInt();
			int id = sc.nextInt();
			if (map.containsKey(id)) {
				map.get(id).add(ts);
			} else {
				map.put(id, new RizhiNode(id, ts));
			}
		}
		sc.close();

		ArrayList<Integer> ans = new ArrayList<>();
		for (Map.Entry<Integer, RizhiNode> entry : map.entrySet()) {
			ArrayList<Integer> list = entry.getValue().list;
			Collections.sort(list);

			int curIdx = 0;
			int curNum = 1;
			for (int i = 1; i < list.size(); i++) {
				if (list.get(curIdx) + D > list.get(i)) {
					curNum++;
				} else {
					while (list.get(curIdx) + D <= list.get(i)) {
						curNum--;
						curIdx++;
					}
					curNum++;
				}
				if (curNum == K) {
					ans.add(entry.getKey());
					curNum = 0;// 防止外面再加一遍
					break;
				}
			}
			if (curNum == K) {
				ans.add(entry.getKey());
			}
		}

		Collections.sort(ans);
		for (int i = 0; i < ans.size(); i++) {
			System.out.println(ans.get(i));
		}
	}
}

class RizhiNode {
	int id;
	ArrayList<Integer> list = new ArrayList<>();

	public RizhiNode(int id, int ts) {
		super();
		this.id = id;
		list.add(ts);
	}

	public void add(int ts) {
		list.add(ts);
	}
}

板块二:今日练习

子串分值(20年省赛)

image-20220402130605490

题目链接:https://www.lanqiao.cn/problems/499/learning/

这个题看一下输入的范围就知道肯定是不能暴力求解了,换个思路想,他要统计一个串中字符恰好出现一次的次数,并且有一个就累积一分,所以其实没必要把所有的串都弄出来,只需要判断一个字符在多少个串中是只出现一次的,那么这个就是关于这个字符的得分,然后遍历整个字符串,统计所有字符的得分就是最终答案

那么现在问题转化成了如何求一个字符的得分,求一个字符的得分就是求他在多少个子串里面是只出现一个的,由于子串是连续的,所以可以以这个字符为中心,向左右两边搜索,直到搜索到和其一样的字符停止,这个就是它在一侧可以到达的范围,最后根据公式 a n s + = ( n u m L e f t + 1 ) ∗ ( n u m R i g h t + 1 ) ans += (numLeft + 1) * (numRight + 1) ans+=(numLeft+1)(numRight+1)即可求出一个字符的得分

问题:这个公式是怎么来的?

  • 一个字符可以组成的子串数量等于它的左边的情况数乘以右边的情况数,由于左边共有 n u m L e f t numLeft numLeft个字符,那么就一共有 n u m L e f t + 1 numLeft+1 numLeft+1中情况(选x个字符和一个都不选的),右侧同理,这样就可以得到这个公式了
package daily;

import java.util.Scanner;

/**
 * https://www.lanqiao.cn/problems/499/learning/
 * 
 * @author Jia
 *
 */
public class day4_2_1 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.nextLine();
		sc.close();

		int ans = 0;
		for (int i = 0; i < str.length(); i++) {
			int numLeft = 0;
			int numRight = 0;
			int idx = i - 1;
			// 统计左侧
			char ch = str.charAt(i);
			while (idx >= 0 && str.charAt(idx) != ch) {
				numLeft++;
				idx--;
			}

			// 统计右侧
			idx = i + 1;
			while (idx < str.length() && str.charAt(idx) != ch) {
				numRight++;
				idx++;
			}

			// 统计总数量
			ans += (numLeft + 1) * (numRight + 1);

		}
		System.out.println(ans);
	}
}

小数第n位(17年国赛)

image-20220402131754695

题目链接:https://www.lanqiao.cn/problems/116/learning/

这个不会,感觉是数论东西,可能有什么神奇的公式吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Hydrion-Qlz

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

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

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

打赏作者

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

抵扣说明:

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

余额充值