2023年第十四届蓝桥杯JavaB组省赛文件已上传到csdn,可自行下载
蓝桥杯题目:2023年第十四届蓝桥杯大赛软件类省赛Java大学B组真题 - 题库 - C语言网 (dotcpp.com)
详细完整题解在这篇博客:
A、阶乘求和
【问题描述】
令 S = 1! + 2! + 3! + ... + 202320232023!,求 S 的末尾 9 位数字。
提示:答案首位不为 0。
Ⅰ、题目解读
一看到三个2023的巨大数字,我想大家应该都人都麻了。但是我想说这是官方的骗术,因为题目说要求末尾的9位数,其实我想告诉大家当加到40多的阶乘时,这个阶乘和后面的9位数就不会发生改变了。
Ⅱ、代码
public class Main { public static void main(String[] args) { long start=1; String s="202320232023"; long end= Long.parseLong(s); long sum=0; long cj=1; while (start<=end){ cj*=start; cj%=1000000000; sum+=cj; sum%=1000000000; start++; if (start>40) System.out.println(sum); } System.out.println(sum); } }
看运行
20940313 420940313 420940313 420940313 420940313 420940313 420940313 ...
这是因为40的阶乘之后后面 9位数都是0,所以阶乘之和末尾9位数不会再发生改变!
B、幸运数字
【问题描述】
哈沙德数是指在某个固定的进位制当中,可以被各位数字之和整除的正整 数。例如 126 是十进制下的一个哈沙德数,因为 (126) 10 mod (1+2+6) = 0 ; 126 也是八进制下的哈沙德数,因为 (126) 10 = (176) 8 , (126) 10 mod (1 + 7 + 6) = 0 ; 同时 126 也是 16 进制下的哈沙德数,因为 (126) 10 = (7 e ) 16 , (126) 10 mod (7 + e ) = 0 。小蓝认为,如果一个整数在二进制、八进制、十进制、十六进制下均为 哈沙德数,那么这个数字就是幸运数字,第 1 至第 10 个幸运数字的十进制表示 为:1 , 2 , 4 , 6 , 8 , 40 , 48 , 72 , 120 , 126 . . . 。现在他想知道第 2023 个幸运数 字是多少?你只需要告诉小蓝这个整数的十进制表示即可。
Ⅰ、题目解读
这题就是考察大家的进制转换,数据量也不大。直接看代码吧!
Ⅱ、代码
public class { public static void main(String[] args) { int j=0; for (int i=1;i<10000000;i++){ if (BaseConversion(i)){ j++; if (j==2023){ System.out.println(i);//215040 break; } } } } public static boolean BaseConversion(int n){ //十进制 int sum=0; int x=n; while (x!=0){ sum+=(x%10); x/=10; } if (n%sum!=0) return false; //二进制 sum=0; x=n; while (x!=0){ sum+=(x%2); x/=2; } if (n%sum!=0) return false; //八进制 sum=0; x=n; while (x!=0){ sum+=(x%8); x/=8; } if (n%sum!=0) return false; //十六进制 int[] arr={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; sum=0; x=n; while (x!=0){ sum+=(arr[x%16]); x/=16; } if (n%sum!=0) return false; return true; } }
C: 数组分割(时间限制: 1.0s 内存限制: 512.0MB)
时间限制: 1.0s
内存限制: 512.0MB
本题总分:10 分
【问题描述】
小蓝有一个长度为 N 的数组 A = [ A 0 , A 1 , . . . , A N − 1 ] 。现在小蓝想要从 A 对应的数组下标所构成的集合 I = { 0 , 1 , 2 , . . . , N − 1 } 中找出一个子集 R 1 ,那么 R 1在 I 中的补集为 R 2 。记 S 1 = ∑ r ∈ R 1 A r , S 2 = ∑ r ∈ R 2 A r,我们要求 S 1 和 S 2 均为 偶数,请问在这种情况下共有多少种不同的 R 1。当 R1 或 R 2 为空集时我们将 S 1 或 S 2 视为 0。
【输入格式】
第一行一个整数 T ,表示有 T 组数据。 接下来输入 T 组数据,每组数据包含两行:第一行一个整数 N ,表示数组 A 的长度;第二行输入 N 个整数从左至右依次为 A 0 , A 1 , . . . , A N − 1 ,相邻元素之 间用空格分隔。
【输出格式】
对于每组数据,输出一行,包含一个整数表示答案,答案可能会很大,你
需要将答案对 1000000007 进行取模后输出。
【样例输入】
2 2 6 6 2 1 6
【样例输出】
4
【样例说明】
对于第一组数据,答案为 4 。(注意:大括号内的数字表示元素在数组中的下标。)
R 1 = { 0 } , R 2 = { 1 } ;此时 S 1 = A 0 = 6 为偶数 , S 2 = A 1 = 6 为偶数。
R 1 = { 1 } , R 2 = { 0 } ;此时 S 1 = A 1 = 6 为偶数 , S 2 = A 0 = 6 为偶数。
R 1 = { 0 , 1 } , R 2 = {} ;此时 S 1 = A 0 + A 1 = 12 为偶数 , S 2 = 0 为偶数。
R 1 = {} , R 2 = { 0 , 1 } ;此时 S 1 = 0 为偶数 , S 2 = A 0 + A 1 = 12 为偶数。
对于第二组数据,无论怎么选择,都不满足条件,所以答案为 0 。
【评测用例规模与约定】
对于 20 % 的评测用例, 1 ≤ N ≤ 10 。
对于 40 % 的评测用例, 1 ≤ N ≤ 10 2 。
对于 100 % 的评测用例, 1 ≤ T ≤ 10 , 1 ≤ N ≤ 10 3 , 0 ≤ A i ≤ 10 9 。
Ⅰ、解题思路
要求分割两个子集,其中一个可以为空集,且两个集合为偶数,所有第一步判断集合的总和是否为偶数,如果不为偶数则直接判定为 0 个否则再进行深度收搜判断 (暴力超时)
也可以利用奇数个数与偶数个数的排列组合实现, 将两个奇数拼接为一个偶数,判断无重复的奇数拼接情况,与偶数个数相加,递推排列组合公式 (正解)
优化排列组合,会发现是高精度算法 设 x 为偶数个数, y 为奇数个数ans = pow(x + (y == 0 ? 0 : y - 1)) % mod 算法标签:递推,找规律,贪心
注意事项:
x + (y == 0 ? 0 : y - 1), 奇数为0情况
Ⅱ、代码
//排列组合递推公式 import java.util.Scanner; import java.math.BigInteger; public class Main { public static final BigInteger MOD = new BigInteger("1000000007"); public static void main(String[] args) { Scanner scan = new Scanner(System.in); int T = scan.nextInt(); while (T-- > 0){ int n = scan.nextInt(); int[] a = new int[n]; long x = 0, y = 0; // x 记录偶数, y 记录奇数 for(int i = 0; i < n; i++){ a[i] = scan.nextInt() % 2; if(a[i] == 0){ x++; }else { y++; } } if(y % 2 == 1){ // 奇数个数为奇,没有一个条件成立 System.out.println(0); continue; } x = x + (y == 0 ? 0 : y - 1); // 两个奇数组合为一个偶数,排除重复情况 BigInteger ans = new BigInteger("2"); BigInteger dp = new BigInteger("1"); // C(n,m) = P(n,m) / P(m,m) = n! / m! * (n - m)! // 转移递推公式 dp = (dp * (x, x-1, x-2, ... , n) / (1, 2, 3, ... , n)) for(long i = 1, j = x; i < x; i++, j--){ // 排列组合无顺序 C BigInteger u = new BigInteger(String.valueOf(j)); BigInteger v = new BigInteger(String.valueOf(i)); dp = dp.multiply(u).divide(v); ans = ans.add(dp); } System.out.println(ans.mod(MOD)); } } }
优化高精度
import java.util.Scanner; import java.math.BigInteger; public class Main { public static final BigInteger MOD = new BigInteger("1000000007"); public static final BigInteger TWO = new BigInteger("2"); public static void main(String[] args) { Scanner scan = new Scanner(System.in); int T = scan.nextInt(); while (T-- > 0) { int n = scan.nextInt(); int x = 0, y = 0; // x 记录偶数, y 记录奇数 for (int i = 0; i < n; i++) { int a = scan.nextInt() % 2; if (a == 0) { x++; } else { y++; } } if (y % 2 == 1) { System.out.println(0); }else{ System.out.println(TWO.pow(x + (y == 0 ? 0 : y - 1)).mod(MOD)); } } } }
D、矩形总面积(时间限制: 1.0s 内存限制: 512.0MB)
【问题描述】
平面上有个两个矩形 R 1 和 R 2 ,它们各边都与坐标轴平行。设 ( x 1 , y 1 ) 和 (x 2 , y 2 ) 依次是 R 1 的左下角和右上角坐标, ( x 3 , y 3 ) 和 ( x 4 , y 4 ) 依次是 R 2 的左下 角和右上角坐标,请你计算 R 1 和 R 2 的总面积是多少?
注意:如果 R 1 和 R 2 有重叠区域,重叠区域的面积只计算一次。
【输入格式】
输入只有一行,包含 8 个整数,依次是: x 1 , y 1 , x 2 , y 2 , x 3 , y 3 , x 4 和 y 4 。
【输出格式】
一个整数,代表答案。
【样例输入】
2 1 7 4 5 3 8 6
【样例输出】
22
【样例说明】
样例中的两个矩形如图所示:
【评测用例规模与约定】
对于 20 % 的数据, R 1 和 R 2 没有重叠区域。
对于 20 % 的数据,其中一个矩形完全在另一个矩形内部。
对于 50 % 的数据,所有坐标的取值范围是 [0 , 10³ ] 。
对于 100 % 的数据,所有坐标的取值范围是 [0 , 10⁵ ]
Ⅰ、题目解读
这题有两种解法,自己数组去求,但是可能数据量过大会爆栈。第二种就是公式直接求解,这时求两个矩形相交的面积改怎么求?
矩形相交要使条件成立,即min(x2,x4)-max(x1,x3)>=0 且min(y2,y4)-max(y1,y3)>=0
如果条件成立,则相交矩形面积为:(min(x2,x4)-max(x1,x3))* (min(y2,y4)-max(y1,y3))
Ⅱ、代码
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int x1 = sc.nextInt(); int y1 = sc.nextInt(); int x2 = sc.nextInt(); int y2 = sc.nextInt(); int x3 = sc.nextInt(); int y3 = sc.nextInt(); int x4 = sc.nextInt(); int y4 = sc.nextInt(); long area1 = (long) (x2 - x1) * (y2 - y1); // 计算第一个矩形的面积 long area2 = (long) (x4 - x3) * (y4 - y3); // 计算第二个矩形的面积 long overlapArea=0; long l = Math.min(x2, x4) - Math.max(x1, x3); long w= Math.min(y2,y4)-Math.max(y1,y3); if (l >=0&&w >=0){ overlapArea= l * w; } long Area = area1 + area2 - overlapArea; // 总面积 System.out.println(Area); // 输出总面积 } }