第十二届蓝桥杯决赛 软件赛JAVA B组决赛题目 2021年6月5日


说明:

  • 本篇文章主要作用是分享下题目。
  • 本人就学过一周算法(学的搜索、动态规划也没用上),所以求解办法主要还是暴力破解。
  • 答案是今天我提交的结果,肯定有不对的,欢迎大佬纠正。

试题A: 整数范围

【问题描述】

  • 用8 位二进制(一个字节)来表示一个非负整数,表示的最小值是0,则一般能表示的最大值是多少?
答案:255

试题B: 纯质数

【问题描述】

  • 如果一个正整数只有1 和它本身两个约数,则称为一个质数(又称素数)。
    前几个质数是:2, 3, 5, 7, 11, 13, 17,19, 23, 29, 31, 37,…… 。
    如果一个质数的所有十进制数位都是质数,我们称它为纯质数。例如:2,3, 5, 7, 23, 37 都是纯质数,而11, 13, 17, 19, 29, 31 不是纯质数。
    当然1, 4, 35也不是纯质数。 请问,在1到20210605 中,有多少个纯质数?
答案:1903

代码:

public class Main{
	// 每位只能包含
	// 2 3 5 7
	// 1903
	public static void main(String[] args) {
		int sum = 0;
		for (int i = 2; i <= 20210605; i++) {
			if (g(i)) {
				if (f(i)) {
					System.out.println(i);
					sum++;
				}
			}
		}
		System.out.println(sum);
	}

	// 判断a是否满足题意
	public static boolean f(int a) {
		int n;
		while (a != 0) {
			n = a % 10;
			if (n != 2 && n != 3 && n != 5 && n != 7)
				return false;
			a /= 10;
		}
		return true;
	}

	// 判断a是否为质数
	public static boolean g(int a) {
		for (int i = 2; i * i <= a; i++) {
			if (a % i == 0)
				return false;
		}
		return true;
	}
}

试题C: 完全日期

【问题描述】

  • 如果一个日期中年月日的各位数字之和是完全平方数,则称为一个完全日 期。
    例如:2021 年6 月5 日的各位数字之和为2 + 0 + 2+ 1 + 6 + 5 = 16,而 16 是一个完全平方数,它是4 的平方。所以2021 年6 月5 日是一个完全日期。
    例如:2021 年6 月23 日的各位数字之和为2 + 0 + 2 + 1 + 6 + 2 + 3 = 16, 是一个完全平方数。所以2021 年6月23 日也是一个完全日期。
    请问,从2001 年1 月1 日到2021 年12 月31 日中,一共有多少个完全日期?
答案:977

代码:

public class Main3 {
	// 977
	public static void main(String[] args) {
		int sum = 0;
		for (int i = 2001; i <= 2021; i++) {
			for (int j = 1; j <= 12; j++) {
				int day = getDay(i, j);
				for (int k = 1; k <= day; k++) {
					if (f(i, j, k)) {
						// System.out.println(i);
						// System.out.println(j);
						// System.out.println(k);
						// System.out.println();
						sum++;
					}
				}
			}
		}
		System.out.println(sum);
	}
	// 获得某年某月的天数
	public static int getDay(int y, int m) {
		switch (m) {
		case 1:	case 3:	case 5:	case 7:	case 8:	case 10:case 12:
			return 31;
		case 4:	case 6:	case 9:	case 11:
			return 30;
		}
		if (m == 2) {
			if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))	{
				return 29;
			} else {
				return 28;
			}
		}
		return 0;
	}
	// 判断是否满足题意
	public static boolean f(int y, int m, int d) {
		int sum = 0;
		while (y != 0) {
			sum += y % 10;
			y /= 10;
		}
		while (m != 0) {
			sum += m % 10;
			m /= 10;
		}
		while (d != 0) {
			sum += d % 10;
			d /= 10;
		}

		for (int i = 1; i * i <= sum; i++) {
			if (i * i == sum)
				return true;
		}
		return false;
	}
}

试题D: 最小权值

【问题描述】

  • 对于一棵有根二叉树T,小蓝定义这棵树中结点的权值W(T) 如下:
    空子树的权值为0。
    如果一个结点v 有左子树L,右子树R,分别有C(L) 和C® 个结点,
    则 W(v) = 1 + 2W(L) + 3W( R ) + (C(L))² C( R )。
    树的权值定义为树的根结点的权值。
    小蓝想知道,对于一棵有2021 个结点的二叉树,树的权值最小可能是多少?
答案:没学数据结构,此题不会

试题E: 大写

【问题描述】

  • 给定一个只包含大写字母和小写字母的字符串,请将其中所有的小写字母 转换成大写字母后将字符串输出。

【输入格式】

  • 输入一行包含一个字符串。

【输出格式】

  • 输出转换成大写后的字符串。

【样例输入1】

  • LanQiao

【样例输出1】

  • LANQIAO

【评测用例规模与约定】

  • 对于所有评测用例,字符串的长度不超过100。

代码:

import java.util.Scanner;
public class N12FS5 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        s = s.toUpperCase();
        System.out.println(s);
    }
}

试题F: 123

【问题描述】

  • 小蓝发现了一个有趣的数列,这个数列的前几项如下: 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, …
    小蓝发现,这个数列前1 项是整数1,接下来2 项是整数1 至2,接下来 3 项是整数1 至3,接下来4 项是整数1 至4,依次类推。
    小蓝想知道,这个数列中,连续一段的和是多少。

【输入格式】

  • 输入的第一行包含一个整数T,表示询问的个数。
    接下来T 行,每行包含一组询问,其中第i 行包含两个整数li 和ri,表示询问数列中第li
    个数到第ri 个数的和。

【输出格式】

  • 输出T 行,每行包含一个整数表示对应询问的答案。

【样例输入】
3
1 1
1 3
5 8
【样例输出】
1
4
8
【评测用例规模与约定】

  • 对于10% 的评测用例,1 ≤ T ≤ 30, 1 ≤ li ≤ ri ≤ 100。
    对于所有评测用例,1 ≤ T ≤ 100000, 1 ≤ li ≤ ri ≤ 10的12次方。

代码:

import java.util.Scanner;

public class Main {
	static final long N = 1000000000000l;
	// 用于存放连续i个数开始的位置为arr[i]
	static long[] arr = new long[1500000];
	// 用于存放1+2+……+i=sumarr[i]
	static long[] sumarr = new long[1500000];

	public static void main(String[] args) {
		init();
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		for (int i = 0; i < n; i++) {
			long l = sc.nextLong();
			long r = sc.nextLong();
			if (l == r) {
				long begin = 0;
				long beginIndex = 0;
				for (int j = 1; j <= 1414215; j++) {
					if (arr[j] > l) {
						begin = arr[j - 1];
						beginIndex = j - 1;
						break;
					}
				}
				int j;
				for (j = 1; j <= l - begin; j++) {
				}
				System.out.println(j);
				continue;
			}
			long begin = 0;
			long beginIndex = 0;
			long end = 0;
			long endIndex = 0;
			int j;
			for (j = 1; j <= 1414215; j++) {
				if (arr[j] > l) {
					begin = arr[j - 1];
					beginIndex = j - 1;
					break;
				}
			}
			for (j = j; j <= 1414215; j++) {
				if (arr[j] > r) {
					end = arr[j - 1];
					endIndex = j - 1;
					break;
				}
			}

			long sum = 0;
			for (long k = beginIndex + 1; k < endIndex; k++) {
				sum += sumarr[(int) k];
			}
			for (long k = l - arr[(int) beginIndex] + 1; k <= beginIndex; k++) {
				sum += k;
			}
			for (int k = 1; k <= r - arr[(int) endIndex] + 1; k++) {
				sum += k;
			}
			System.out.println(sum);
		}
	}

	public static void init() {
		long sum = 1;
		long sumar = 0;
		arr[1] = 1;
		for (long i = 1; i < 1000000000000l; i++) {
			sumar += i;
			sumarr[(int) i] = sumar;
			sum += i;
			arr[(int) (i + 1)] = arr[(int) i] + i;
			if (sum > N) {
				sumarr[(int) (i + 1)] = sum;
				break;
			}
		}
	}
}

试题G: 和与乘积

【问题描述】

  • 给定一个数列A = (a1, a2, ……, an),问有多少个区间[L, R] 满足区间内元素 的乘积等于他们的和,即aL * aL+1 * …… * aR = aL + aL+1 + + …… + + aR 。

【输入格式】

  • 输入第一行包含一个整数n,表示数列的长度。
    第二行包含n 个整数,依次表示数列中的数a1, a2, ……, an。

【输出格式】

  • 输出仅一行,包含一个整数表示满足如上条件的区间的个数。

【样例输入】
4
1 3 2 2
【样例输出】
6
【样例解释】
符合条件的区间为[1, 1], [1, 3], [2, 2], [3, 3], [3, 4], [4, 4]。
【评测用例规模与约定】

  • 对于20% 的评测用例,n, m ≤ 3000;
    对于50% 的评测用例,n, m ≤ 20000;
    对于所有评测用例,1 ≤ n, m≤ 200000, 1 ≤ ai ≤ 200000。

代码:

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
	static int[] arr;
	static int n;

	public static void main(String[] args) {
		init();
		BigInteger b1;
		BigInteger b2;
		long sum = 0;
		for (int i = 0; i < n; i++) {
			b1 = BigInteger.ONE;
			b2 = BigInteger.ZERO;
			for (int j = i; j < n; j++) {
				BigInteger bj = BigInteger.valueOf(arr[j]);
				b1 = b1.multiply(bj);
				b2 = b2.add(bj);
				if (b1.equals(b2)) {
					sum++;
				}
			}
		}
		System.out.println(sum);
	}

	public static void init() {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = sc.nextInt();
		}
	}
}

试题H: 巧克力

【问题描述】

  • 小蓝很喜欢吃巧克力,他每天都要吃一块巧克力。
    一天小蓝到超市想买一些巧克力。超市的货架上有很多种巧克力,每种巧克力有自己的价格、数量和剩余的保质期天数,小蓝只吃没过保质期的巧克力, 请问小蓝最少花多少钱能买到让自己吃x 天的巧克力。

【输入格式】

  • 输入的第一行包含两个整数x、n,分别表示需要吃巧克力的天数和巧克力 的种类数。
    接下来n 行描述货架上的巧克力,其中第i行包含三个整数ai, bi, ci,表示 第 i 种巧克力的单价为ai,保质期还剩bi 天(从现在开始的bi 天可以吃),数量为ci。

【输出格式】
输出一个整数表示小蓝的最小花费。如果不存在让小蓝吃x 天的购买方案,输出-1。
【样例输入】
10 3
1 6 5
2 7 3
3 10 10
【样例输出】
18
【样例说明】

  • 一种最佳的方案是第1 种买5 块,第2 种买2 块,第3 种买3 块。前5 天 吃第1 种,第6、7 天吃第2 种,第8 至10 天吃第3种。

【评测用例规模与约定】
对于30% 的评测用例,n、x ≤ 1000。
对于所有评测用例,1 ≤ n、x ≤ 100000,1 ≤ ai,bi,ci ≤ 10的9次方。

待更

试题I: 翻转括号序列

【问题描述】

  • 给定一个长度为n 的括号序列,要求支持两种操作:
    1.将[Li,Ri] 区间内(序列中的第Li 个字符到第Ri 个字符)的括号全部翻转(左括号变成右括号,右括号变成左括号)。
    2.求出以Li 为左端点时,最长的合法括号序列对应的Ri(即找出最大的 Ri 使[Li,Ri] 是一个合法括号序列)。

【输入格式】

  • 输入的第一行包含两个整数n;m,分别表示括号序列长度和操作次数。
    第二行包含给定的括号序列,括号序列中只包含左括号和右括号。
    接下来m行,每行描述一个操作。如果该行为“1 Li Ri”,表示第一种操作, 区间为[Li,Ri] ;如果该行为“2 Li”表示第二种操作,左端点为Li。

【输出格式】
对于每个第二种操作,输出一行,表示对应的Ri。如果不存在这样的Ri,请输出0。
【样例输入】
7 5
((())()
2 3
2 2
1 3 5
2 3
2 1
【样例输出】
4
7
0
0
【评测用例规模与约定】
对于20% 的评测用例,n,m ≤ 5000;
对于40% 的评测用例,n,m ≤ 30000;
对于60% 的评测用例,n,m ≤ 100000;
对于所有评测用例,1 ≤ n ≤ 10的6次方, 1 ≤ m ≤ 2 * 10的5次方。

待更

试题J: 异或三角

【问题描述】

  • 给定T 个数n1,n2,……,nT,对每个ni 请求出有多少组a,b,c 满足:
    1、1 ≤ a,b,c ≤ ni;
    2、a ⊕ b ⊕ c = 0,其中⊕表示二进制按位异或;
    3、长度为a,b,c 的三条边能组成一个三角形。

【输入格式】
输入的第一行包含一个整数T。
接下来T 行每行一个整数,分别表示n1,n2,……, nT。
【输出格式】
输出T 行,每行包含一个整数,表示对应的答案。
【样例输入】
2
6
114514
【样例输出】
6
11223848130
【评测用例规模与约定】
对于10% 的评测用例,T = 1; 1 ≤ ni ≤ 200;
对于所有评测用例,1 ≤ T ≤ 100000; 1 ≤ ni ≤ 2的30次方。

待更
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值