大家好,我是snippet,今天是刷蓝桥真题的第十二天,今天的题目内容包含求素数和二分,下面是我今天的题解
目录
一、0的个数
题目链接:0 的个数 - 蓝桥云课 (lanqiao.cn)
题目内容:
问题描述
给定一个正整数 n ,请问 n 的十进制表示中末尾总共有几个 0 ?
输入格式
输入一行包含一个正整数 n。
输出格式
输出一个整数,表示答案。
样例输入
20220000
样例输出
4
评测用例规模与约定
对于所有评测用例,1 <= n <= 1000000000。
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
解题思路:
求一个数的末尾0的个数,那我们直接从这个数的个数开始取模即可
代码:
package 蓝桥杯31天真题冲刺.Day12;
import java.util.Scanner;
/**
* @author snippet
* @data 2023-03-15
* 0的个数-蓝桥云课
*/
public class T1_0的个数 {
static long n;
static int ans;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextLong();
while (true) {
if (n % 10 == 0) {
ans++;
n /= 10;
} else {
break;
}
}
System.out.println(ans);
}
}
二、超级质数
题目内容:
问题描述
如果一个质数 P 的每位数字都是质数, 而且每两个相邻的数字组成的两位 数是质数, 而且每三位相邻的数字组成的三位数是质数, 依次类推, 如果每相 邻的 k 位数字组成的 k 位数都是质数, 则 P 称为超级质数。
如果把超级质数 P 看成一个字符串, 则这个超级质数的每个子串都是质 数。
例如, 53 是一个超级质数。
请问, 最大的超级质数是多少?
答案提交
这是一道结果填空的题, 你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
解题思路:
这个题求最大的超级质数(超级质数:这个数是质数,以及它的每个数位的数都是质数,它不管怎么拆分也仍然是质数),我们先用埃式筛求质数,然后再对这个数每个数位取模判断是不是质数,最后再求连续的数位是不是质数;
代码:
package 蓝桥杯31天真题冲刺.Day12;
import java.util.Arrays;
/**
* @author snippet
* @data 2023-03-15
* 超级质数-蓝桥云课
*/
public class T2_超级质数 {
static int N = 10000000;
static boolean[] is_prime = new boolean[N+1];
static int ans;
// 埃式筛判断是不是素数
static void prime() {
for (int i = 2; i <= N; i++) {
if (is_prime[i]) {
for (int j = 2; i*j <= N; j++) {
is_prime[i*j] = false;
}
}
}
}
// 判断这个数的每个位数是不是素数
static boolean one_prime(int n) {
while (n > 0) {
int t = n % 10;
if (!is_prime[t]) {
return false;
}
n /= 10;
}
return true;
}
// 判断连续的数字是不是素数
static boolean t_prime(int n) {
String s = Integer.toString(n);
for (int i = 0; i < s.length(); i++) {
for (int j = i+1; j <= s.length(); j++) {
String str = s.substring(i,j);
if (!is_prime[Integer.parseInt(str)]) return false;
}
}
return true;
}
public static void main(String[] args) {
Arrays.fill(is_prime, true);
is_prime[0] = false;
is_prime[1] = false;
prime();
for (int i = 0; i <= N; i++) {
if (is_prime[i] && one_prime(i) && t_prime(i)) {
ans = Math.max(ans, i);
}
}
System.out.println(ans);
}
}
三、卡牌
题目内容:
问题描述
这天, 小明在整理他的卡牌。
他一共有 n 种卡牌, 第 i 种卡牌上印有正整数数 i(i∈[1,n]), 且第 i 种卡牌 现有 ai 张。
而如果有 n 张卡牌, 其中每种卡牌各一张, 那么这 n 张卡牌可以被称为一 套牌。小明为了凑出尽可能多套牌, 拿出了 m 张空白牌, 他可以在上面写上数 i, 将其当做第 i 种牌来凑出套牌。然而小明觉得手写的牌不太美观, 决定第 i 种牌最多手写 bi 张。
请问小明最多能凑出多少套牌?
输入格式
输入共 3 行, 第一行为两个正整数 n,m 。
第二行为 n 个正整数 a1,a2,…,an 。
第三行为 n 个正整数 b1,b2,…,bn 。
输出格式
一行, 一个整数表示答案。
样例输入
4 5
1 2 3 4
5 5 5 5
样例输出
3
样例说明
这 5 张空白牌中, 拿 2 张写 1 , 拿 1 张写 2 , 这样每种牌的牌数就变为了3,3,3,4, 可以凑出 3 套牌, 剩下 2 张空白牌不能再帮助小明凑出一套。
评测用例规模与约定
对于 30% 的数据, 保证 n≤2000;
对于 100% 的数据, 保证 n≤2×105;ai,bi≤2n;m≤n2 。
运行限制
- 最大运行时间:1s
- 最大运行内存: 512M
解题思路:
这个题,我们可以用二分找到合适的卡牌套数,然后就是我们的check()函数,判断牌的套数是否合适的时候,每个目标套数对每种牌都有四大种情况:
1.第i种牌的原始牌的数量 >= 目标套数 => 这种牌满足目标套数
2.第i种牌的原始数+最大补满数都 < 目标套数 => 这个目标套数不满足
3.该i种牌补写之后满足目标数&&有足够的空白牌来补写牌 => 这种牌满足目标套数
4.不够空白牌来补写牌了 => 这个目标套数不满足
当每种牌同时满足1或3时,该目标套数满足条件
代码:
package 蓝桥杯31天真题冲刺.Day12;
import java.io.*;
/**
* @author snippet
* @data 2023-03-15
* 卡牌-蓝桥云课
*/
// 二分答案
public class T3_卡牌 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static long n,m;// n表示牌的种类 m表示可补的牌的数量(空白牌的数量)
static int N = 200100;
static int[] a = new int[N];// 一维数组a存牌的原始数据
static int[] b = new int[N];// 一维数组b存牌的是第i种牌的最大补写牌的数量
// x表示牌的目标套数
static boolean check(int x) {
// v表示还剩余的空牌的数量
long v = m;
// 算牌的套数的时候 有四种情况
for (int i = 1; i <= n; i++) {
// 1.第i种牌的原始牌的数量 >= 目标套数
if (a[i] >= x) continue;
// 2.补满牌都不够目标套数
if (a[i] + b[i] < x) return false;
// 3.该种牌补写牌之后满足目标牌数 && 够空白牌的补写
if (a[i] + b[i] >= x && v >= x - a[i]) {
v = v - (x - a[i]);
} else {
// 4. 不够空白牌的补写
return false;
}
}
return true;
}
public static void main(String[] args) throws IOException {
String[] s = br.readLine().split(" ");
n = Long.parseLong(s[0]);
m = Long.parseLong(s[1]);
s = br.readLine().split(" ");
for (int i = 1; i <= n; i++) {
a[i] = Integer.parseInt(s[i-1]);
}
s = br.readLine().split(" ");
for (int i = 1; i <= n; i++) {
b[i] = Integer.parseInt(s[i-1]);
}
int left = 0;
int right = 2*N;
while (left < right) {
int mid = left + right + 1 >> 1;
if (check(mid)) left = mid;
else right = mid-1;
}
pw.println(left);
pw.flush();
br.close();
}
}
四、染色时间
这个题好像是用 优先级队列+BFS,我不是很用的明白,我就写了个暴力,过了1个案例 哈哈哈