2023第十四届蓝桥杯Java B组(A-F)真题,暴力骗分

前言

        本人菜鸡一枚,如有错误,评论区指正,本文主要为算法新手在比赛中骗分提供一些思路,这皆是我的一家之言,大伙看个乐就行了。

一、A:阶乘求和

S = 1! + 2! + 3! + ... + 202320232023!,求 S 的末尾 9 位数字。
提示:答案首位不为 0。
public class Main{ 
        public static void main(String[] args) {
                long sum=0; 
                long t=1000000000; 
                long temp=1; 
                for(int i=1;i<=100;i++){         
                        temp=(temp*i)%t; 
                        sum=(sum+temp)%t;       
                } 
                System.out.println(sum); 
        }
 }

2f67289c3bc34be6932d4a6de138fb30.png

 总结

这题不能用暴力解决,毕竟10的11次方了。这题只要求观察出1!到39!之和后面的末尾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 Main{
    public static void main(String[] args) {
        int count=0;
        while(true){
            for(long i=1;;i++){
                if(Is(i,2)&&Is(i,8)&&Is(i,10)&&Is(i,16)){
                    count++;
                    if(count==2023){
                        System.out.println(i);
                        return;
                    }
                }
            }
        }
    }
    static boolean Is(long num,int n){
        long t=num;
        int sum=0;
        while(t!=0){
            sum=(int)(sum+(t%n));
            t/=n;
        }
        return num%sum==0;
    }
}

总结

答案:215040

简单进制转换。long换成int也是可以的,不会爆

三、C: 数组分割

小蓝有一个长度为 N 的数组 A = [ A0, A1, . . . , A N−1]。现在小蓝想要从 A 对 应的数组下标所构成的集合 I = {0, 1, 2, . . . , N − 1} 中找出一个子集 R1,那么 R1 在 I 中的补集为 R2。记 S 1 = ∑ rR1 A rS 2 = ∑ rR2 A r,我们要求 S 1 和 S 2 均为 偶数,请问在这种情况下共有多少种不的
R1。当 R1 或 R2 为空集时我们将 S 1 或 S 2 视为 0。 该处使用的url网络请求的数据。
【输入格式】
第一行一个整数 T,表示有 T 组数据。
接下来输入 T 组数据,每组数据包含两行:第一行一个整数 N,表示数组
A 的长度;第二行输入 N 个整数从左至右依次为 A0, A1, . . . , A N−1,相邻元素之
间用空格分隔。
【输出格式】
对于每组数据,输出一行,包含一个整数表示答案,答案可能会很大,你
需要将答案对 1000000007 进行取模后输出
【样例输入】
2
2
6 6
2
1 6
【样例输出】
4
0
对于第一组数据,答案为 4。(注意:大括号内的数字表示元素在数组中的
下标。)
R1 = {0}, R2 = {1};此时 S 1 = A0 = 6 为偶数, S 2 = A1 = 6 为偶数。
R1 = {1}, R2 = {0};此时 S 1 = A1 = 6 为偶数, S 2 = A0 = 6 为偶数。
R1 = {0, 1}, R2 = {};此时 S 1 = A0 + A1 = 12 为偶数, S 2 = 0 为偶数。
R1 = {}, R2 = {0, 1};此时 S 1 = 0 为偶数, S 2 = A0 + A1 = 12 为偶数。
对于第二组数据,无论怎么选择,都不满足条件,所以答案为 0。
【评测用例规模与约定】
对于 20% 的评测用例,1 ≤ N ≤ 10。
对于 40% 的评测用例,1 ≤ N ≤ 100。
对于 100% 的评测用例,1 ≤ T ≤ 10, 1 ≤ N ≤ 1000 , 0 ≤ A i ≤ 1e9。
import java.util.Scanner;

public class Main{
    static int T;
    static long ans=0;
    static int[] arr;
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        T=in.nextInt();
        while (T!=0){
            int n=in.nextInt();
            arr=new int[n+1];
            long sum=0;
            for (int i = 1; i <=n; i++) {
                arr[i]=in.nextInt();
                sum+=arr[i];
            }
            if (sum%2==0){
                ans++;
            }
            for (int i=1;i<=n;i++){
                bfs(i+1,sum,arr[i]);
            }
            System.out.println(ans);
            ans=0;
            T--;
        }
    }
    static void bfs(int next,long sum,long sum_temp){
        if(sum_temp%2==0&&(sum-sum_temp)%2==0){
            ans++;
            ans=ans%1000000007;
        }
        for (int i=next;i<arr.length;i++){
            bfs(i+1,sum,sum_temp+arr[i]);
        }
    }
}

总结

本人这题没有审题已寄,我以为是计算全部然后输出(样例的4,0是分页的),这题ans过大的话可能要用BigInteger处理。这题只需考虑{}和{全部}的关系,应该是能骗些分的

四、 D: 矩形总面积

平面上有个两个矩形 R1 和 R2,它们各边都与坐标轴平行。设 ( x1, y1) 和
( x2, y2) 依次是 R1 的左下角和右上角坐标,( x3, y3) 和 ( x4, y4) 依次是 R2 的左下
角和右上角坐标,请你计算 R1 和 R2 的总面积是多少?
注意:如果 R1 和 R2 有重叠区域,重叠区域的面积只计算一次。
【输入格式】
输入只有一行,包含 8 个整数,依次是: x1, y1, x2, y2, x3, y3, x4 和 y4。
【输出格式】
一个整数,代表答案。
【样例输入】
2 1 7 4 5 3 8 6
【样例输出】
22
【评测用例规模与约定】
对于 20% 的数据, R1 和 R2 没有重叠区域。
对于 20% 的数据,其中一个矩形完全在另一个矩形内部。
对于 50% 的数据,所有坐标的取值范围是 [0, 103 ]。
对于 100% 的数据,所有坐标的取值范围是 [0, 105 ]。
import java.util.HashSet;
import java.util.Scanner;

public class Main{
    static HashSet<String> hs=new HashSet<>();
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        int x1,y1,x2,y2,x3,y3,x4,y4;
        x1=in.nextInt();
        y1=in.nextInt();
        x2=in.nextInt();
        y2=in.nextInt();
        x3=in.nextInt();
        y3=in.nextInt();
        x4=in.nextInt();
        y4=in.nextInt();
        for (int i=x1;i<x2;i++){
            for(int j=y1;j<y2;j++){
                String str=""+i+"-"+j;
                hs.add(str);
            }
        }
        for (int i=x3;i<x4;i++){
            for(int j=y3;j<y4;j++){
                String str=""+i+"-"+j;
                hs.add(str);
            }
        }
        System.out.println(hs.size());
    }
}

总结

模拟题,普通判断的话会有很多种情况,有时间的话可以思考一下,我大概估计有10+种,面积大应该会超时,骗分吧


五、E: 蜗牛

这天,一只蜗牛来到了二维坐标系的原点。
x 轴上长有 n 根竹竿。它们平行于 y 轴,底部纵坐标为 0,横坐标分别
x1, x2, ..., x n。竹竿的高度均为无限高,宽度可忽略。蜗牛想要从原点走到第
n 个竹竿的底部也就是坐标 ( x n, 0)。它只能在 x 轴上或者竹竿上爬行,在 x
上爬行速度为 1 单位每秒;由于受到引力影响,蜗牛在竹竿上向上和向下爬行
的速度分别为 0.7 单位每秒和 1.3 单位每秒。
为了快速到达目的地,它施展了魔法,在第 i i + 1 根竹竿之间建立了传
送门(0 < i < n),如果蜗牛位于第 i 根竹竿的高度为 a i 的位置 ( x i , a i),就可以
瞬间到达第 i + 1 根竹竿的高度为 b i+1 的位置 ( x i+1, b i+1),请计算蜗牛最少需要
多少秒才能到达目的地。
【输入格式】
输入共 1 + n 行,第一行为一个正整数 n
第二行为 n 个正整数 x1, x2, . . . , x n
后面 n − 1 行,每行两个正整数 a i , b i+1。
【输出格式】
输出共一行,一个浮点数表示答案(四舍五入保留两位小数)。
【样例输入】
3
1 10 11
1 1
2 1
【样例输出】
4.20
【样例说明】
蜗牛路线:
(0, 0) → (1, 0) → (1, 1) → (10, 1) → (10, 0) → (11, 0),花费时间为 1 + 0 1
.7 +
0 + 1 1
.3 + 1 ≈ 4.20
【评测用例规模与约定】
对于 20% 的数据,保证 n ≤ 15;
对于 100% 的数据,保证 n ≤ 105, a i , b i ≤ 104, x i ≤ 109。
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;

public class Main{
    static HashSet<String> hs=new HashSet<>();
    static long[] arr;
    static int[][] ab;
    static int n;
    static long x;
    static int y;
    static double t;
    public static void main(String[] args) {

        Scanner in=new Scanner(System.in);
        n=in.nextInt();
        arr=new long[n];
        for(int i=0;i<n;i++){
            arr[i]=in.nextLong();
        }
        ab=new int[n-1][2];
        for(int i=0;i<n-1;i++){
            ab[i][0]=in.nextInt();
            ab[i][1]=in.nextInt();
        }
        double min=Integer.MAX_VALUE;
        dfs("",0);
        Iterator<String> iterator = hs.iterator();
        while (iterator.hasNext()) {
            char[] next = iterator.next().toCharArray();
            t=arr[0];
            x=arr[0];
            y=0;
            get(next,0);
            t=t+(y-0)*(10*1.0/13);
            min=Math.min(t,min);
        }
        min+=0.005;
        System.out.println(String.format("%.2f",min));
    }
    static void get(char[] chars,int index){
        if(x==arr[n-1]){
            return ;
        }
        if (chars[index]=='0'){
            t=t+y*(10*1.0/13);
            t=t+arr[index+1]-arr[index];
            x=arr[index+1];
            y=0;
        }else{
            if (y>ab[index][0]){
                t=t+(y-ab[index][0])*(10*1.0/13);
            }else{
                t=t+(ab[index][0]-y)*(10*1.0/7);
            }
            x=arr[index+1];
            y=ab[index][1];
        }
        index++;
        get(chars,index);
    }
    static void dfs(String str,int count){
        if(count==n-1){
            hs.add(str);
            return;
        }
        char a='0',b='1';
        count=count+1;
        dfs(str+a,count);
        dfs(str+b,count);
    }
}

总结

只能过30%左右的数据,没办法就只能暴力,喜欢拼运气可以直接随机。这里我不知道是自愿传送还是碰到那个点就会传送

六、F: 合并区域

小蓝在玩一款种地游戏。现在他被分配给了两块大小均为 N × N 的正方形
区域。这两块区域都按照 N × N 的规格进行了均等划分,划分成了若干块面积
相同的小区域,其中每块小区域要么是岩石,要么就是土壤,在垂直或者水平
方向上相邻的土壤可以组成一块土地。现在小蓝想要对这两块区域沿着边缘进
行合并,他想知道合并以后可以得到的最大的一块土地的面积是多少(土地的
面积就是土地中土壤小区域的块数)?
在进行合并时,小区域之间必须对齐。可以在两块方形区域的任何一条边
上进行合并,可以对两块方形区域进行 90 度、180 度、270 度、360 度的旋转,
但不可以进行上下或左右翻转,并且两块方形区域不可以发生重叠。
【输入格式】
第一行一个整数 N 表示区域大小。
接下来 N 行表示第一块区域,每行 N 个值为 0 或 1 的整数,相邻的整数
之间用空格进行分隔。值为 0 表示这块小区域是岩石,值为 1 表示这块小区域
是土壤。
再接下来 N 行表示第二块区域,每行 N 个值为 0 或 1 的整数,相邻的整
数之间用空格进行分隔。值为 0 表示这块小区域是岩石,值为 1 表示这块小区
域是土壤。
【输出格式】
一个整数表示将两块区域合并之后可以产生的最大的土地面积。
【样例输入】
4
0 1 1 0
1 0 1 1
1 0 1 0
1 1 1 0
0 0 1 0
0 1 1 0
1 0 0 0
1 1 1 1
【样例输出】
15
对于 30% 的数据,1 ≤ N ≤ 5。
对于 60% 的数据,1 ≤ N ≤ 15。
对于 100% 的数据,1 ≤ N ≤ 50。
import java.util.Scanner;

public class Main{
	static int[][] arr1;
	static int[][] arr2;
	static int N;
	public static void main(String[] args){
		Scanner in=new Scanner(System.in);
		N=in.nextInt();
		arr1=new int[N][N];
		arr2=new int[N][N];
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				arr1[i][j]=in.nextInt();
			}
		}
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				arr2[i][j]=in.nextInt();
			}
		}
		int max=0;
		int max1=0;
		int max2=0;
		for(int i=0;i<N;i++){
			if(arr1[i][N-1]==1){
				max1=Math.max(max1,get(i,N-1));
			}
			if(arr1[N-1][i]==1){
				max1=Math.max(max1,get(N-1,i));
			}
			if(arr1[i][0]==1){
				max1=Math.max(max1,get(i,0));
			}
			if(arr1[0][i]==1){
				max1=Math.max(max1,get(0,i));
			}
		}
		max+=max1;
		for(int i=0;i<N;i++){
			if(arr2[i][N-1]==1){
				max2=Math.max(max2,get1(i,N-1));
			}
			if(arr2[N-1][i]==1){
				max2=Math.max(max2,get1(N-1,i));
			}
			if(arr2[i][0]==1){
				max2=Math.max(max2,get1(i,0));
			}
			if(arr2[0][i]==1){
				max2=Math.max(max2,get1(0,i));
			}
		}
		max+=max2;
		System.out.println(max);
	}
	static int get(int x,int y){
		int[][] arr=new int[N][N];
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				arr[i][j]=arr1[i][j];
			}
		}
		arr1[x][y]=2;
		if(x-1>=0&&arr1[x-1][y]==1){
			bfs(x-1,y);
		}
		if(x+1<N&&arr1[x+1][y]==1){
			bfs(x+1,y);
		}
		if(y-1>=0&&arr1[x][y-1]==1){
			bfs(x,y-1);
		}
		if(y+1<N&&arr1[x][y+1]==1){
			bfs(x,y+1);
		}
		int count=0;
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				if(arr1[i][j]==2){
					count++;
				}
			}
		}
		arr1=arr;
		return count;
	}
	static void bfs(int x,int y){
		arr1[x][y]=2;
		if(x-1>=0&&arr1[x-1][y]==1&&arr1[x-1][y]!=2){
			bfs(x-1,y);
		}
		if(x+1<N&&arr1[x+1][y]==1&&arr1[x+1][y]!=2){
			bfs(x+1,y);
		}
		if(y-1>=0&&arr1[x][y-1]==1&&arr1[x][y-1]!=2){
			bfs(x,y-1);
		}
		if(y+1<N&&arr1[x][y+1]==1&&arr1[x][y+1]!=2){
			bfs(x,y+1);
		}
	}
	static int get1(int x,int y){
		int[][] arr=new int[N][N];
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				arr[i][j]=arr2[i][j];
			}
		}
		arr2[x][y]=2;
		if(x-1>=0&&arr2[x-1][y]==1){
			bfs1(x-1,y);
		}
		if(x+1<N&&arr2[x+1][y]==1){
			bfs1(x+1,y);
		}
		if(y-1>=0&&arr2[x][y-1]==1){
			bfs1(x,y-1);
		}
		if(y+1<N&&arr2[x][y+1]==1){
			bfs1(x,y+1);
		}
		int count=0;
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				if(arr2[i][j]==2){
					count++;
				}
			}
		}
		arr2=arr;
		return count;
	}
	static void bfs1(int x,int y){
		arr2[x][y]=2;
		if(x-1>=0&&arr2[x-1][y]==1&&arr2[x-1][y]!=2){
			bfs1(x-1,y);
		}
		if(x+1<N&&arr2[x+1][y]==1&&arr2[x+1][y]!=2){
			bfs1(x+1,y);
		}
		if(y-1>=0&&arr2[x][y-1]==1&&arr2[x][y-1]!=2){
			bfs1(x,y-1);
		}
		if(y+1<N&&arr2[x][y+1]==1&&arr2[x][y+1]!=2){
			bfs1(x,y+1);
		}
	}
}

总结

bfs暴搜,选择最大值即可,也是考完才想起来直接报搜,大佬们看个乐就行了,明年蓝桥杯再见

吐槽

总体难度比往年差不多,就是简单题不再是白送分了。第一次参加蓝桥杯也很紧张。点名批评一下广东某水利学院的设备和监考老师的态度,手机响了不管?害我开局少考20+分钟,紧张体验感拉满

  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值