2023年第十四届蓝桥杯将至来看看第十二届蓝桥杯javaB组题目如何
Posted quicklysleep
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2023年第十四届蓝桥杯将至来看看第十二届蓝桥杯javaB组题目如何相关的知识,希望对你有一定的参考价值。
ฅ(๑˙o˙๑)ฅ 大家好, 欢迎大家光临我的博客:面向阿尼亚学习
算法学习笔记系列持续更新中~
文章目录
一、前言
过两天就要考蓝桥杯了,今年报的java组,下午做了套第十二届蓝桥杯java组真题
分享一下
5道填空,5道编程
二、2021年蓝桥杯javaB组省赛真题目录
A、B、C、D、E为填空题
A:ASC[5分]
思路⭐
%%%
代码🌟
public class Main
public static void main(String[] args)
System.out.println((int)'L');
答案:76
B 卡片(5分)
思路⭐
模拟
注意审题
可以从1拼到多少,结果记得减一
代码🌟
public class Main
static int a[] = new int[10];
public static void main(String[] args)
for (int i = 0; i <= 9; i++)
a[i] = 2021;
for (int i = 1; i <= 10000; i++)
int x = i;
while (x != 0)
if (a[x % 10] == 0) //如果卡片不够了,输出并返回
System.out.println(i - 1);// 注意是可以从1拼到多少
return;
a[x % 10]--;
x = x / 10;
答案:3181
C 直线(10分)
思路⭐
枚举所有的点构成的直线,计算出斜率和截距,用来唯一表示一条直线
技巧用字符串类型Set,但要注意化简分数
代码🌟
import java.util.HashSet;
import java.util.Set;
public class Main
static int gcd(int a, int b)
if (b == 0)
return a;
else
return gcd(b, a % b);
public static void main(String[] args)
// 用字符串类型,方便去重
Set<String> lines = new HashSet<>();
// 循环所有的点
for (int x1 = 0; x1 < 20; x1++)
for (int x2 = 0; x2 < 20; x2++)
for (int y1 = 0; y1 < 21; y1++)
for (int y2 = 0; y2 < 21; y2++)
if (x1 == x2 || y1 == y2)
continue;
String line = "orz";// 分隔符没啥意义
// 计算斜率
int y = y2 - y1;
int x = x2 - x1;
int d = gcd(x, y);// 出最小公倍数化简
String k = y / d + "/" + x / d;
line += k + "orz";
// 计算截距
int m = y2 * x1 - y1 * x2;
int n = gcd(m, x);
line += m / n + "/" + x / n;
lines.add(line);
// 最后答案要加上k = 0及b = 0的情况
System.out.println(lines.size() + 20 + 21);
答案:40257
D 货物摆放(10分)
思路⭐
很明显枚举可以做,但是数量级有点大
技巧:我们只要枚举其所有因子即可
代码🌟
import java.util.ArrayList;
import java.util.List;
public class Main
public static void main(String[] args)
Long num = new Long("2021041820210418");
// 从因子集合里面找结果
List<Long> set = new ArrayList<>();
for (long i = 1; i * i <= num; i++)
if (num % i == 0)
set.add(i);
if (num / i != i) // 不相等加上
set.add(num / i);
int res = 0;
for (long i : set)
for (long j : set)
for (long t : set)
if (i * j * t == num)
res++;
System.out.println(res);
答案:2430
E 路径(15分)
思路⭐
动态规划
毕竟最短路的本质就是动态规划
代码🌟
public class Main
static final int N = 2022;
static int[] f = new int[N];// f[i]表示1到n的最短距离
static int gcd(int a, int b)
if (b == 0)
return a;
else
return gcd(b, a % b);
public static void main(String[] args)
for (int i = 1; i <= 2021; i++)
for (int j = i + 1; j <= i + 21 && j <= 2021; j++)
if (f[j] == 0)
f[j] = f[i] + i * j / gcd(i, j);// i*j/gcd(i*j)为最小公倍数
else
f[j] = Math.min(f[j], f[i] + i * j / gcd(i, j));
System.out.println(f[2021]);
答案:10266837
以下为编程题
F 时间显示 (15分)
思路⭐
%%%如题所示
代码🌟
import java.util.Scanner;
public class Main
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
// 先把毫秒转化成秒
n = n / 1000;
// 求最后一天的秒数
n = n % (24 * 60 * 60);
// 求显示的小时
long hour = n / (60 * 60);
// 这个小时内的秒数
n = n % (60 * 60);
// 求分钟
long min = n / 60;
// 求秒
long s = n % 60;
System.out.printf("%02d:%02d:%02d", hour, min, s);
G 最少砝码(20分)
思路⭐
- 1个砝码数最大称出所有小于等于
1
的正整数数量 - 2个砝码数最大称出所有小于等于
4
的正整数数量 - 3个砝码数最大称出所有小于等于
13
的正整数数量 - 公式:当前砝码最大称重=上一级砝码最大称重 ×
3
+1
代码🌟
import java.util.Scanner;
public class Main
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int res = 0;
for (int i = 1;; i++)
res = res * 3 + 1;
if (res >= n)
System.out.println(i);
return;
H 杨辉三角 (20分)
思路⭐
根据杨辉三角形找规律,二分
代码🌟
import java.util.Scanner;
public class Main
static int n;
static long C(int a, int b)
long res = 1;
for (int i = a, j = 1; j <= b; i--, j++)
res = res * i / j;
if (res > n)
return res;// 不用大于n
return res;
static boolean check(int k)
long l = k * 2, r = Math.max((long) n, l);
while (l < r)
long mid = l + r >> 1;
if (C((int) mid, k) >= n)
r = mid;
else
l = mid + 1;
if (C((int) r, k) != n)
return false;
System.out.println(r * (r + 1) / 2 + k + 1);
return true;
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int k = 16;; k--)
if (check(k))
break;
I 双向排序 (25分)
思路⭐
暴力骗分
能过60%
代码🌟
import java.util.Arrays;
import java.util.Scanner;
public class Main
static final int N = 100007;
static Integer[] a = new Integer[N];
static int n, m;
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for (int i = 1; i <= n; i++)
a[i] = i;
while (m-- > 0)
int p = sc.nextInt();
int q = sc.nextInt();
if (p == 0)
Arrays.sort(a, 1, q + 1, (o1, o2) -> o2 - o1);//降序
else
Arrays.sort(a, q, n + 1);//升序
for (int i = 1; i <= n; i++)
System.out.print(a[i] + " ");
J 搬砖 (25分)
思路⭐
动态规划
代码🌟
import java.util.Scanner;
public class Main
static int N = 5010;
static int MOD = (int) 1e9 + 7;
static int n;
static char[] str = new char[N];
static long[][] f;
public static void main(String[] args)
Scanner sc = new Scanner(System.in);
String s = sc.next();
sc.close();
str = (" " + s).toCharArray();
n = s.length();
long l = work();
str = (" " + reverse(s)).toCharArray();
for (int i = 1; i <= n; i++)
if (str[i] == '(')
str[i] = ')';
else
str[i] = '(';
long r = work();
System.out.println(l * r % MOD);
private static long work()
f = new long[N][N];
f[0][0] = 1;
for (int i = 1; i <= n; i++)
if (str[i] == '(')
for (int 第十二届蓝桥杯C++赛后感
注:有些代码忘了考试时怎么写的了,(我也懒得重新写),所以很多题的代码是acwing蓝桥杯讲解里的,我对其进行注释和修改
A 空间
32位程序中,INT变量占用4个字节
1mb=1024kb
1kb=1024B
1B=8b
B:byte
b:bit
32位二进制数是四个字节
实际上就是求256MB有多少个32 bit
答案:256*1024*1024/4
= 67108864
卡片
直接模拟即可
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b)
typedef long long ll;
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
int a[10];
bool iff(int x)
{
while (x)
{
int y = x % 10;
if (a[y])
a[y]--;
else
return 0;
x /= 10;
}
return 1;
}
int main() {
for (int i = 0; i <= 9; i++) a[i] = 2021;
for (int i = 1;; i++)
{
if (!iff(i))
{
cout << i - 1 << endl;
break;
}
}
return 0;
}
答案:3181
直线
比赛时用set实现的,忘了自己做的对不对。。
我当时做的方法是因为两点确定一线,所以枚举两个点,然后用set记录斜率和截距(y=k*x+b),但是k有可能不存在,所以最后的答案还要额外加上20
当时代码懒得写了,按照其他博主的写法重新写的,只不过用的不是set,存下所有k和b后,排序,将重复的k和b删掉
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b)
typedef long long ll;
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
const int maxn = 200000;
double eps=1e-8;
int n;
struct Line
{
double k, b;
bool operator< (const Line& t) const
{
if (k != t.k) return k < t.k;
return b < t.b;
}
}L[maxn];
int main()
{
for (int x1 = 0; x1 < 20; x1 ++ )
for (int y1 = 0; y1 < 21; y1 ++ )
for (int x2 = 0; x2 < 20; x2 ++ )
for (int y2 = 0; y2 < 21; y2 ++ )
if (x1 != x2)
{
double k = (double)(y2 - y1) / (x2 - x1);
double b = y1 - k * x1;
L[n ++ ] = {k, b};//存两点所形成的直线
}
sort(L, L +maxn);
int res = 1;
for (int i = 1; i < n; i ++ )
if (fabs(L[i].k - L[i - 1].k) > eps || fabs(L[i].b - L[i - 1].b) > eps)//说明不是一条直线
res ++ ;
cout << res + 20 << endl;//加20是因为k不存在的直线也要考虑
return 0;
}
我当时的做法是对的,但是最后的答案忘了是不是这个
答案:40257
货物摆放
LWH都是n的约数,问有多少种方案,其实就是求n的约数,用这些约数进行组合。因为约数不是很多,所以三重循环枚举约数,看是否等于n
对n求约束,直接开方求就行(因为如果x是约数,那么n/x也是,所以只需要将范围缩小到根号n)
(比赛时我是这么做的,确信)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
int main()
{
LL n;
cin >> n;
vector<LL> d;
for (LL i = 1; i * i <= n; i ++ )
if (n % i == 0)
{
d.push_back(i);
if (n / i != i) d.push_back(n / i);
}
int res = 0;
for (auto a: d)
for (auto b: d)
for (auto c: d)
if (a * b * c == n)
res ++ ;
cout << res << endl;
return 0;
}
答案:2430
路径
就是一个建边跑最短路。。比赛时忘了gcd咋写emm
好像有的用dp来做?
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2200, M = N * 50;
int n;
int h[N], e[M], w[M], ne[M], idx;
int q[N], dist[N];
bool st[N];
int gcd(int a, int b) // 欧几里得算法
{
return b ? gcd(b, a % b) : a;
}
void add(int a, int b, int c) // 添加一条边a->b,边权为c
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
void spfa() // 求1号点到n号点的最短路距离
{
int hh = 0, tt = 0;
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
q[tt ++ ] = 1;
st[1] = true;
while (hh != tt)
{
int t = q[hh ++ ];
if (hh == N) hh = 0;
st[t] = false;
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
if (!st[j]) // 如果队列中已存在j,则不需要将j重复插入
{
q[tt ++ ] = j;
if (tt == N) tt = 0;
st[j] = true;
}
}
}
}
}
int main()
{
n = 2021;
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++ )
for (int j = max(1, i - 21); j <= min(n, i + 21); j ++ )
{
int d = gcd(i, j);
add(i, j, i * j / d);
}
spfa();
printf("%d\\n", dist[n]);
return 0;
}
答案:10266837
时间显示
比赛时忘了1s等于多少ms,还好电脑自带计算器里有时间的进制关系(狗头🐕)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int main()
{
LL n;
cin >> n;
n /= 1000;
n %= 86400;
int h = n / 3600;
n %= 3600;
int m = n / 60;
int s = n % 60;
printf("%02d:%02d:%02d\\n", h, m, s);
return 0;
}
G砝码称重
背包问题
自己对dp真的不熟。。五一要好好练练dp
对于每个砝码他有三个选择,称的左侧,右侧和不放,
我们设dp[i][j]表示前i个物品中,总质量为j的情况是否存在,dp为bool型
对于第j个物品,我们说了有三种选择,所以我们可以得到转移方程:
分别对应不选,放左侧,放右侧
dp[i][j]|=dp[i-1][j]
dp[i][j]|=dp[i-1][j-w[i]]
dp[i][j]|=dp[i-1][j+w[i]]
按照题目要求j-w[i]最小为-m,数组不能用负下标,所以我们加一个偏移量B,保证数组下标都为非负
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110, M = 200010, B = M / 2;
int n, m;
int w[N];
bool f[N][M];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]), m += w[i];
f[0][B] = true;
for (int i = 1; i <= n; i ++ )
for (int j = -m; j <= m; j ++ )
{
f[i][j + B] = f[i - 1][j + B];
if (j - w[i] >= -m) f[i][j + B] |= f[i - 1][j - w[i] + B];
if (j + w[i] <= m) f[i][j + B] |= f[i - 1][j + w[i] + B];
}
int res = 0;
for (int j = 1; j <= m; j ++ )
if (f[n][j + B])
res ++ ;
printf("%d\\n", res);
return 0;
}
H杨辉三角形
因为杨辉三角形左右对称,所以我们只考虑左半部分
我们进行枚举可以看出,斜列的数量不会超过20个,所以枚举每一个斜列,每个斜列的第一个元素也是递增排列且有关系(第一个斜列的首元素为C(1,0),第二个为C(1,2),第三个为C(2,4),…C(x,2x)),斜列内的元素是递增排列的,且大小都有公式关系(比如第3个斜列,第一个元素是C(2,4),第二个元素是C(2,5),然后是C(2,6)…),然后二分找具体位置
如果第C(r,k)是我们要找的元素,他的位置就是r * (r + 1) / 2 + k + 1
思维题
妙啊,当时写了一个半暴力,真想不到
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int n;
LL C(int a, int b)
{
LL res = 1;
for (int i = a, j = 1; j <= b; i --, j ++ )
{
res = res * i / j;
if (res > n) return res;
}
return res;
}
bool check(int k)
{
//C(a,b)
//a>=2b,二分a
LL l = k * 2, r = n;
while (l < r)
{
LL mid = l + r >> 1;
if (C(mid, k) >= n) r = mid;
else l = mid + 1;
}
if (C(r, k) != n) return false;
cout << r * (r + 1) / 2 + k + 1 << endl;
return true;
}
int main()
{
cin >> n;
for (int k = 16; ; k -- )
if (check(k))
break;
return 0;
}
双向排列
J括号序列
肯定是dp,但是我不会。。。等会了再更新
以上是关于2023年第十四届蓝桥杯将至来看看第十二届蓝桥杯javaB组题目如何的主要内容,如果未能解决你的问题,请参考以下文章