ฅ(๑˙o˙๑)ฅ 大家好, 欢迎大家光临我的博客:面向阿尼亚学习
算法学习笔记系列持续更新中~
过两天就要考蓝桥杯了,今年报的java组,今天上午做了一套第十三届蓝桥杯javaB组真题
分享一下
2道填空,8道编程
A、B为填空题
本人用的快速幂取余7
然后看看比星期六多几天就可以了
import java.util.Scanner;
public class Main {
static long qpow(int a, int b, int p) {
long sum = 1;
while (b != 0) {
if ((b & 1) == 1) {
sum = sum * a % p;
}
a = a * a % p;
b >>= 1;
}
return sum;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println(qpow(20, 22, 7));
}
}
答案:7
模拟
写两个check函数
暴力枚举符合条件的
import java.util.Scanner;
public class Main {
static boolean check1(int x) {
String s = Integer.toString(x);
char c[] = s.toCharArray();
int j = c.length - 1;
for (int i = 0; i < j; i++, j--) {
if (c[i] != c[j])
return false;
}
return true;
}
static boolean check2(int x) {
String s = Integer.toString(x);
char c[] = s.toCharArray();
int len = s.length();
int mid;
if (len % 2 == 0)
mid = len / 2;
else {
mid = len / 2 + 1;
}
for (int i = 0; i < mid - 1; i++) {
if (c[i] > c[i + 1])
return false;
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int ans = 0;
for (int i = 2022; i <= 2022222022; i++) {
if (check1(i)) {
if (check2(i)) {
ans++;
System.out.println(i);
}
// System.out.println(i);
}
}
System.out.println(ans);
}
}
//3138
答案:3138
以下为编程题
开个哈希表存储每个字母出现的次数
然后遍历两次
第一次求出现次数的最大值
第二次将出现次数等于最大值的字母输出即可
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.next();
Map<Character, Integer> mp = new HashMap<>();
char[] c = s.toCharArray();
for (char o = 'A'; o <= 'Z'; o++) {
mp.put(o, 0);
}
for (int i = 0; i < s.length(); i++) {
int x = mp.get(c[i]);
x++;
mp.put(c[i], x);
}
int maxx = -1;
for (char o = 'A'; o <= 'Z'; o++) {
maxx = Math.max(maxx, mp.get(o));
}
for (char o = 'A'; o <= 'Z'; o++) {
if (mp.get(o) == maxx)
System.out.print(o);
}
}
}
记录刷不同题目同学的数量
然后对其求前缀和
然后可以在O(1)的时间范围求出比某个同学刷题数多的同学
或者比他刷题少的同学
然后二分求解刷题数,结果减去原本的刷题数即可
import java.io.*;
public class Main {
static int N = 200010;
static int[] a = new int[N], cnt = new int[N];
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
int n = Integer.parseInt(br.readLine());
String[] s = br.readLine().split(" ");
for (int i = 0; i < n; i++) {// 输入每个同学的刷题数保存到 a 数组中
a[i] = Integer.parseInt(s[i]);
cnt[a[i]]++;
}
// 前缀和
for (int i = 1; i <= 100000; ++i) {
cnt[i] += cnt[i - 1];
}
for (int i = 0; i < n; ++i) {
// 如果比他刷题多的同学不大于比他小的同学,就不需要刷题了,直接输出0
if (cnt[100000] - cnt[a[i]] <= cnt[Math.max(0, a[i] - 1)]) {
out.print(0 + " ");
continue;
}
// 否则进行二分
int l = a[i], r = 100000;
while (l + 1 < r) {// 开区间
int mid = l + r >> 1;
if (cnt[100000] - cnt[mid] <= cnt[mid - 1] - 1) {
r = mid;
} else {
l = mid;
}
}
out.print((r - a[i]) + " ");
}
out.flush();
}
}
求后缀0的个数,我们可以根据阶乘的因子中2和5的个数确实,因为2*5=10,后缀多一个0
而2的个数要多于5的个数,所有只要求5的个数即可
因此后缀0的个数与n存在单调关系可以二分求
注意开long
import java.util.Scanner;
public class Main {
static long k;
// 求阶乘末尾0的个数其实就是求阶乘因子中5的个数
static boolean check(long x) {
long res = 0;
//欧几里得公式
while (x != 0) {
res += x / 5;
x /= 5;
}
return res >= k;
}
static long find() {
long l = 1, r = Long.MAX_VALUE - 4;
while (l + 1 < r) {
long mid = (l + r) / 2;
if (check(mid)) {
r = mid;
} else {
l = mid;
}
}
return r;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
k = sc.nextLong();
// System.out.println(find());
long ans = 0;
long p = find();
while (p != 0) {
ans += p / 5;
p /= 5;
}
if (ans != k)
System.out.println(-1);
else {
System.out.println(find());
}
}
}
暴力
四个循环
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
String[] ss = in.readLine().split(" ");
int n = Integer.parseInt(ss[0]);
int m = Integer.parseInt(ss[1]);
int[][] g = new int[n][m];
for (int i = 0; i < n; i++) {
ss = in.readLine().split(" ");
for (int j = 0; j < m; j++)
g[i][j] = Integer.parseInt(ss[j]);
}
int limit = Integer.parseInt(in.readLine());
int res = 1;
for (int i = 0; i < n; i++)// 枚举 行首
for (int j = 0; j < m; j++)// 枚举 列首
for (int x = i; x < n; x++)// 枚举 行尾
{
int kx = Integer.MAX_VALUE;
int ky = Integer.MAX_VALUE;
for (int y = j; y < m; y++)// 枚举 列尾
{
if (x >= kx && y >= ky)
continue;
if (check(g, i, j, x, y) <= limit)// 判断最大差
{
res = Math.max(res, (x - i + 1) * (y - j + 1));
} else {
kx = x;
ky = y;
break;
}
}
}
System.out.println(res);
}
private static int check(int[][] g, int xs, int ys, int xe, int ye) {
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int i = xs; i <= xe; i++)
for (int j = ys; j <= ye; j++) {
max = Math.max(max, g[i][j]);
min = Math.min(min, g[i][j]);
}
return max - min;
}
}
如果是一段连续的自然数,满足这段区间的最大值-最小值=区间长度
然后进行动态规划
import java.util.Scanner;
public class Main {
static final int N = 10007;
static final int mod = 1000000007;
static int[] a = new int[N];
static int[] f = new int[N];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++)
a[i] = sc.nextInt();
f[0] = 1;
for (int i = 1; i <= n; i++) {
int maxx = Integer.MIN_VALUE;
int minn = Integer.MAX_VALUE;
for (int j = i; j >= 1; j--) {
maxx = Math.max(maxx, a[j]);
minn = Math.min(minn, a[j]);
if (maxx - minn == i - j)
f[i] = (f[i] + f[j - 1]) % mod;
}
}
System.out.println(f[n]);
}
}
构造题
用数组表示状态
static int[][] a=new int[N][N];// 0表示没填,1表示空地,2表示墙,3表示墙外的点(外面的墙)
最后的输出
if(a[i][j] == 1 || a[i][j] == 3) System.out.printf(" "); //空地和外面的墙都要画空格
else System.out.printf("*"); //只要不是外面的墙,那么画墙
状态计算模拟即可
import java.util.Scanner;
public class Main {
static final int N=507;
static int[][] a=new int[N][N];// 0表示没填,1表示空地,2表示墙,3表示墙外的点(外面的墙)
static int[] dx= {1,0,-1,0};
static int[] dy= {0,1,0,-1};
static int maxD=-1,maxR=-1;
static int minU=507,minL=507;
static void bfs(int sx, int sy) // 将围在墙外的点标记为3
{
PII[] q = new PII[N * N];
int hh = 0, tt = -1;
q[++ tt] = new PII(sx, sy);
while(hh <= tt)
{
PII t = q[hh ++];
int x = t.x, y = t.y;
for(int i = 0; i < 4; i ++) {
int xx = x + dx[i], yy = y + dy[i];
if(xx >= 0 && xx <=500 && yy >= 0 && yy <=500 && a[xx][yy] == 0) {
a[xx][yy] = 3;
q[++ tt] = new PII(xx, yy);
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String s = sc.next();
// System.out.println(s);
int x=200,y=200;
a[x][y]=1;
char c[]=s.toCharArray();
for(int i=0;i<n;i++){
if(c[i]=='U')
{
x--;
a[x][y]=1;
}
else if(c[i]=='D')
{
x++;
a[x][y]=1;
}
else if(c[i]=='L')
{
y--;
a[x][y]=1;
}
else if(c[i]=='R'){
y++;
a[x][y]=1;
}
}
// int maxD=-1,maxR=-1;
// int minU=507,minL=507;
for(int i=0;i<=500;i++)
{
for(int j=0;j<=500;j++)
{
if(a[i][j]==1)
{
maxD=Math.max(maxD, i);
maxR=Math.max(maxR, j);
minU=Math.min(minU, i);
minL=Math.min(minL, j);
for(int k=0;k<4;k++)
{
int xx=i+dx[k];
int yy=j+dy[k];
if(a[xx][yy]!=1)
{
a[xx][yy]=2;
}
}
}
}
}
bfs(0, 0);
// System.out.println(minU-1);
// System.out.println(maxD+1);
// System.out.println(minL-1);
// System.out.println(maxR+1);
for(int i=minU-1;i<=maxD+1;i++)
{
for(int j=minL-1;j<=maxR+1;j++)
{
if(a[i][j] == 1 || a[i][j] == 3) System.out.printf(" "); //空地和外面的墙都要画空格
else System.out.printf("*"); //只要不是外面的墙,那么画墙
// System.out.print(a[i][j]);
}
System.out.println();
}
/*
17
UUUULLLLDDDDRRRRU
20
RRULUDLLULLRUURUULLU
*/
}
}
class PII {
int x, y;
PII(int x, int y) {
this.x = x;
this.y = y;
}
}
%%%
%%%
祝考的都会