【2024年华为OD机试】 (C卷,100分)- 工号不够用了怎么办?(Java JS PythonC/C++)
一、问题描述
题目描述
背景
在3020年,空间通信集团的员工人数已突破20亿,现有的工号系统面临容量不足的问题。为解决这一问题,需要设计一个新的工号系统。
工号格式要求
新工号系统应包含小写英文字母(a-z)和数字(0-9)。具体要求如下:
工号以英文字母序列开头,后跟数字序列,例如:“aaahw0001”、“a12345”、“abcd1”、“a00”。
工号不能全为字母或全为数字。
数字部分允许前导零或全零。
为降低记忆难度,需控制工号长度。
任务
给定新工号至少需分配的人数
X
X
和字母长度
Y
Y
,求新工号中数字的最短长度
Z
Z
。
输入格式
一行包含两个非负整数
X
X
和
Y
Y
,用单个空格分隔。
0 < X \leq 2^{50} - 1
0<X≤250−1
0 < Y \leq 5
0<Y≤5
输出格式
输出新工号中数字的最短长度
Z
Z
。
示例
输入:260 1
输出:1
输入:26 1
输出:1
输入:2600 1
输出:2
题目解析
这是一道数学问题。
小写字母有26种,数字有10种。
若工号由一个字母和一个数字组成,共有
26 \times 10 = 260
26×10=260
种组合。
若由两个字母和两个数字组成,则有
26^2 \times 10^2
262×102
种组合。
给定需要的工号总数
x
x
和字母数
y
y
,公式为:
x = 26^y \times 10^z
x=26y×10z
求最小的
z
z
,且
z \geq 1
z≥1
。
求解公式为:
z = \lceil \log_{10} \left( \frac{x}{26^y} \right) \rceil
z=⌈log10(x26y)⌉
其中,
\lceil \cdot \rceil
⌈⋅⌉
表示向上取整。
二、JavaScript算法源码
以下是 JavaScript 代码的详细中文注释和讲解:
JavaScript 代码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline"); // 引入 readline 模块,用于读取控制台输入
// 创建 readline 接口
const rl = readline.createInterface({
input: process.stdin, // 输入流为标准输入
output: process.stdout, // 输出流为标准输出
});
// 监听 'line' 事件,当用户输入一行数据时触发
rl.on("line", (line) => {
// 将输入的一行数据按空格分割,并转换为数字数组
const [x, y] = line.split(" ").map(Number);
// 计算并输出结果
console.log(Math.max(1, Math.ceil(Math.log10(x / Math.pow(26, y)))));
});
代码讲解:
1. 引入模块:
const readline = require("readline")
:- 引入 Node.js 的
readline
模块,用于从控制台读取用户输入。
- 引入 Node.js 的
2. 创建 readline 接口:
rl = readline.createInterface({ input: process.stdin, output: process.stdout })
:- 创建一个
readline
接口对象,指定输入流为标准输入(process.stdin
),输出流为标准输出(process.stdout
)。
- 创建一个
3. 监听输入事件:
rl.on("line", (line) => { ... })
:- 监听
line
事件,当用户输入一行数据并按回车键时触发回调函数。 - 回调函数的参数
line
是用户输入的一行字符串。
- 监听
4. 处理输入数据:
const [x, y] = line.split(" ").map(Number)
:- 将输入的一行字符串按空格分割成数组。
- 使用
map(Number)
将数组中的每个元素转换为数字。 - 使用解构赋值将数组中的前两个元素分别赋值给变量
x
和y
。
5. 计算结果:
Math.pow(26, y)
:- 计算 26 的
y
次方。
- 计算 26 的
x / Math.pow(26, y)
:- 计算
x
除以 26 的y
次方的结果。
- 计算
Math.log10(...)
:- 计算上述结果的以 10 为底的对数。
Math.ceil(...)
:- 将对数结果向上取整。
Math.max(1, ...)
:- 确保最终结果至少为 1(如果计算结果小于 1,则返回 1)。
6. 输出结果:
console.log(...)
:- 输出计算结果。
示例运行:
输入 1:
100 1
- 输出:
1
- 解释:
x = 100
,y = 1
。Math.pow(26, 1) = 26
。x / Math.pow(26, y) = 100 / 26 ≈ 3.846
。Math.log10(3.846) ≈ 0.585
。Math.ceil(0.585) = 1
。Math.max(1, 1) = 1
。
输入 2:
1000 2
- 输出:
2
- 解释:
x = 1000
,y = 2
。Math.pow(26, 2) = 676
。x / Math.pow(26, y) = 1000 / 676 ≈ 1.479
。Math.log10(1.479) ≈ 0.17
。Math.ceil(0.17) = 1
。Math.max(1, 1) = 1
。
输入 3:
100000 3
- 输出:
2
- 解释:
x = 100000
,y = 3
。Math.pow(26, 3) = 17576
。x / Math.pow(26, y) = 100000 / 17576 ≈ 5.69
。Math.log10(5.69) ≈ 0.755
。Math.ceil(0.755) = 1
。Math.max(1, 1) = 1
。
总结:
- 该代码通过读取用户输入的两个数字
x
和y
,计算并输出一个与对数相关的值。 - 核心逻辑是计算
x / 26^y
的对数,并确保结果至少为 1。 - 如果有其他问题,欢迎继续提问!
三、Java算法源码
以下是 Java 代码的详细中文注释和讲解:
Java 代码
import java.util.Scanner; // 引入 Scanner 类,用于读取用户输入
public class Main {
public static void main(String[] args) {
// 创建 Scanner 对象,用于从控制台读取输入
Scanner sc = new Scanner(System.in);
// 读取用户输入的两个值:x 和 y
long x = sc.nextLong(); // 读取一个长整型数值 x
int y = sc.nextInt(); // 读取一个整型数值 y
// 计算并输出结果
System.out.println((long) Math.max(1, Math.ceil(Math.log10(x / Math.pow(26, y)))));
}
}
代码讲解:
1. 引入 Scanner 类:
import java.util.Scanner
:- 引入 Java 的
Scanner
类,用于从控制台读取用户输入。
- 引入 Java 的
2. 创建 Scanner 对象:
Scanner sc = new Scanner(System.in)
:- 创建一个
Scanner
对象sc
,用于从标准输入流(System.in
)读取数据。
- 创建一个
3. 读取用户输入:
long x = sc.nextLong()
:- 从控制台读取一个长整型数值,并将其赋值给变量
x
。
- 从控制台读取一个长整型数值,并将其赋值给变量
int y = sc.nextInt()
:- 从控制台读取一个整型数值,并将其赋值给变量
y
。
- 从控制台读取一个整型数值,并将其赋值给变量
4. 计算结果:
Math.pow(26, y)
:- 计算 26 的
y
次方。
- 计算 26 的
x / Math.pow(26, y)
:- 计算
x
除以 26 的y
次方的结果。
- 计算
Math.log10(...)
:- 计算上述结果的以 10 为底的对数。
Math.ceil(...)
:- 将对数结果向上取整。
Math.max(1, ...)
:- 确保最终结果至少为 1(如果计算结果小于 1,则返回 1)。
(long)
:- 将结果强制转换为
long
类型,以确保输出为整数。
- 将结果强制转换为
5. 输出结果:
System.out.println(...)
:- 输出计算结果。
示例运行:
输入 1:
100 1
- 输出:
1
- 解释:
x = 100
,y = 1
。Math.pow(26, 1) = 26
。x / Math.pow(26, y) = 100 / 26 ≈ 3.846
。Math.log10(3.846) ≈ 0.585
。Math.ceil(0.585) = 1
。Math.max(1, 1) = 1
。
输入 2:
1000 2
- 输出:
1
- 解释:
x = 1000
,y = 2
。Math.pow(26, 2) = 676
。x / Math.pow(26, y) = 1000 / 676 ≈ 1.479
。Math.log10(1.479) ≈ 0.17
。Math.ceil(0.17) = 1
。Math.max(1, 1) = 1
。
输入 3:
100000 3
- 输出:
1
- 解释:
x = 100000
,y = 3
。Math.pow(26, 3) = 17576
。x / Math.pow(26, y) = 100000 / 17576 ≈ 5.69
。Math.log10(5.69) ≈ 0.755
。Math.ceil(0.755) = 1
。Math.max(1, 1) = 1
。
总结:
- 该代码通过读取用户输入的两个值
x
和y
,计算并输出一个与对数相关的值。 - 核心逻辑是计算
x / 26^y
的对数,并确保结果至少为 1。 - 如果有其他问题,欢迎继续提问!
四、Python算法源码
以下是 Python 代码的详细中文注释和讲解:
Python 代码
# 引入 math 模块,用于数学计算
import math
# 从控制台读取用户输入的一行数据,并将其按空格分割成两个整数
x, y = map(int, input().split())
# 定义算法函数
def getResult(x, y):
# 计算并输出结果
print(max(1, math.ceil(math.log10(x / math.pow(26, y)))))
# 调用算法函数
getResult(x, y)
代码讲解:
1. 引入 math 模块:
import math
:- 引入 Python 的
math
模块,用于进行数学计算(如对数、幂运算等)。
- 引入 Python 的
2. 读取用户输入:
x, y = map(int, input().split())
:- 使用
input()
函数从控制台读取用户输入的一行数据。 - 使用
split()
方法将输入字符串按空格分割成列表。 - 使用
map(int, ...)
将列表中的每个元素转换为整数。 - 使用解构赋值将列表中的前两个元素分别赋值给变量
x
和y
。
- 使用
3. 定义算法函数:
def getResult(x, y):
:- 定义一个名为
getResult
的函数,接受两个参数x
和y
。
- 定义一个名为
4. 计算结果:
math.pow(26, y)
:- 计算 26 的
y
次方。
- 计算 26 的
x / math.pow(26, y)
:- 计算
x
除以 26 的y
次方的结果。
- 计算
math.log10(...)
:- 计算上述结果的以 10 为底的对数。
math.ceil(...)
:- 将对数结果向上取整。
max(1, ...)
:- 确保最终结果至少为 1(如果计算结果小于 1,则返回 1)。
5. 输出结果:
print(...)
:- 输出计算结果。
6. 调用算法函数:
getResult(x, y)
:- 调用
getResult
函数,传入用户输入的x
和y
值。
- 调用
示例运行:
输入 1:
100 1
- 输出:
1
- 解释:
x = 100
,y = 1
。math.pow(26, 1) = 26
。x / math.pow(26, y) = 100 / 26 ≈ 3.846
。math.log10(3.846) ≈ 0.585
。math.ceil(0.585) = 1
。max(1, 1) = 1
。
输入 2:
1000 2
- 输出:
1
- 解释:
x = 1000
,y = 2
。math.pow(26, 2) = 676
。x / math.pow(26, y) = 1000 / 676 ≈ 1.479
。math.log10(1.479) ≈ 0.17
。math.ceil(0.17) = 1
。max(1, 1) = 1
。
输入 3:
100000 3
- 输出:
1
- 解释:
x = 100000
,y = 3
。math.pow(26, 3) = 17576
。x / math.pow(26, y) = 100000 / 17576 ≈ 5.69
。math.log10(5.69) ≈ 0.755
。math.ceil(0.755) = 1
。max(1, 1) = 1
。
总结:
- 该代码通过读取用户输入的两个值
x
和y
,计算并输出一个与对数相关的值。 - 核心逻辑是计算
x / 26^y
的对数,并确保结果至少为 1。 - 如果有其他问题,欢迎继续提问!
五、C/C++算法源码:
以下是 C 语言 和 C++ 代码的详细中文注释和讲解:
C 语言代码
#include <stdio.h> // 引入标准输入输出库,用于输入输出操作
#include <math.h> // 引入数学库,用于数学计算(如对数、幂运算等)
int main() {
// 定义变量
double x; // 定义双精度浮点数 x,用于存储用户输入的第一个值
int y; // 定义整数 y,用于存储用户输入的第二个值
// 读取用户输入
scanf("%lf %d", &x, &y); // 从控制台读取用户输入的两个值,分别赋值给 x 和 y
// 计算并输出结果
printf("%d\n", (int) fmax(1.0, ceil(log10(x / pow(26, y)))));
return 0; // 程序正常结束
}
C++ 代码
#include <iostream> // 引入输入输出流库,用于输入输出操作
#include <cmath> // 引入数学库,用于数学计算(如对数、幂运算等)
using namespace std; // 使用标准命名空间
int main() {
// 定义变量
double x; // 定义双精度浮点数 x,用于存储用户输入的第一个值
int y; // 定义整数 y,用于存储用户输入的第二个值
// 读取用户输入
cin >> x >> y; // 从控制台读取用户输入的两个值,分别赋值给 x 和 y
// 计算并输出结果
cout << (int) fmax(1.0, ceil(log10(x / pow(26, y)))) << endl;
return 0; // 程序正常结束
}
代码讲解:
1. 引入头文件:
- C 语言:
#include <stdio.h>
:- 引入标准输入输出库,用于支持
scanf
和printf
等输入输出函数。
- 引入标准输入输出库,用于支持
#include <math.h>
:- 引入数学库,用于支持数学计算函数(如
pow
、log10
、ceil
等)。
- 引入数学库,用于支持数学计算函数(如
- C++:
#include <iostream>
:- 引入输入输出流库,用于支持
cin
和cout
等输入输出操作。
- 引入输入输出流库,用于支持
#include <cmath>
:- 引入数学库,用于支持数学计算函数(如
pow
、log10
、ceil
等)。
- 引入数学库,用于支持数学计算函数(如
2. 定义变量:
- C 语言 和 C++:
double x;
:- 定义一个双精度浮点数变量
x
,用于存储用户输入的第一个值。
- 定义一个双精度浮点数变量
int y;
:- 定义一个整数变量
y
,用于存储用户输入的第二个值。
- 定义一个整数变量
3. 读取用户输入:
- C 语言:
scanf("%lf %d", &x, &y);
:- 使用
scanf
函数从控制台读取用户输入的两个值。 %lf
表示读取一个双精度浮点数,赋值给x
。%d
表示读取一个整数,赋值给y
。
- 使用
- C++:
cin >> x >> y;
:- 使用
cin
从控制台读取用户输入的两个值,分别赋值给x
和y
。
- 使用
4. 计算结果:
- C 语言 和 C++:
pow(26, y)
:- 计算 26 的
y
次方。
- 计算 26 的
x / pow(26, y)
:- 计算
x
除以 26 的y
次方的结果。
- 计算
log10(...)
:- 计算上述结果的以 10 为底的对数。
ceil(...)
:- 将对数结果向上取整。
fmax(1.0, ...)
:- 确保最终结果至少为 1.0(如果计算结果小于 1.0,则返回 1.0)。
(int)
:- 将结果强制转换为整数类型,以便输出。
5. 输出结果:
- C 语言:
printf("%d\n", ...);
:- 使用
printf
函数输出计算结果。 %d
表示输出一个整数。
- 使用
- C++:
cout << ... << endl;
:- 使用
cout
输出计算结果。 endl
表示换行。
- 使用
6. 程序结束:
- C 语言 和 C++:
return 0;
:- 表示程序正常结束。
示例运行:
输入 1:
100 1
- 输出:
1
- 解释:
x = 100.0
,y = 1
。pow(26, 1) = 26.0
。x / pow(26, y) = 100.0 / 26.0 ≈ 3.846
。log10(3.846) ≈ 0.585
。ceil(0.585) = 1.0
。fmax(1.0, 1.0) = 1.0
。- 强制转换为整数后输出
1
。
输入 2:
1000 2
- 输出:
1
- 解释:
x = 1000.0
,y = 2
。pow(26, 2) = 676.0
。x / pow(26, y) = 1000.0 / 676.0 ≈ 1.479
。log10(1.479) ≈ 0.17
。ceil(0.17) = 1.0
。fmax(1.0, 1.0) = 1.0
。- 强制转换为整数后输出
1
。
输入 3:
100000 3
- 输出:
1
- 解释:
x = 100000.0
,y = 3
。pow(26, 3) = 17576.0
。x / pow(26, y) = 100000.0 / 17576.0 ≈ 5.69
。log10(5.69) ≈ 0.755
。ceil(0.755) = 1.0
。fmax(1.0, 1.0) = 1.0
。- 强制转换为整数后输出
1
。
总结:
- C 语言 和 C++ 代码的功能完全相同,只是语法和输入输出方式略有不同。
- 该代码通过读取用户输入的两个值
x
和y
,计算并输出一个与对数相关的值。 - 核心逻辑是计算
x / 26^y
的对数,并确保结果至少为 1。 - 如果有其他问题,欢迎继续提问!