Number - 题解
标签与难度
标签: 构造, 数学, 模拟, 入门, 字符串处理 难度: 800
题目大意喵~
主人你好呀~ 这道题的任务很简单哦!题目会给我们两个正整数,一个叫做 ,另一个是质数 。我们需要找到一个正整数,这个数必须满足两个条件:
- 它必须能被 整除(也就是说,它是 的倍数)。
- 它的位数必须正好是 位。
如果能找到这样一个数,我们就把它打印出来。如果找不到,就要伤心地输出 "T_T",呐。
举个例子,如果 ,我们就可以找到 500。500 是 5 的倍数,而且它正好是 3 位数,完美~!
解题思路分析
喵哈哈,这道题就像是玩一个数字积木游戏!我们要用数字搭建一个符合要求的“城堡”呢。让我来带你一步步分析吧!
首先,我们要构造一个数,它必须是 的倍数。最简单的 的倍数是什么呢?当然是 自己啦!还有 , , 等等,都是 的倍数。
我们的目标是找到一个倍数,它的位数恰好是 。我们应该从哪个倍数入手呢?最简单的想法就是从 本身开始改造,看看能不能把它变成一个 位数,同时还保持是 的倍数。
我们先来看看 自己有多少位。我们可以写一个小小的循环来数一下,就叫这个位数是 len_p 吧。
// 比如 P = 123
int p = 123;
int len_p = 0;
int temp_p = p;
if (temp_p == 0) { // 虽然题目说是正整数,但考虑0是1位哦
len_p = 1;
} else {
while (temp_p > 0) {
temp_p /= 10;
len_p++;
}
}
// 循环结束,len_p 就是 3 啦数完位数之后,就会有两种情况,喵~
情况一:不可能完成的任务 T_T
如果 本身的位数 len_p 就已经超过了我们被允许的位数 (也就是 len_p > N),那该怎么办呢?
想一想,任何一个 的倍数(比如 ,)的大小肯定不会小于 本身。如果 都有 len_p 位了,那么它的倍数至少也有 len_p 位。既然 len_p 都比 大了,那我们无论如何也找不到一个位数更少的、又是 的倍数的数了。就像让你用一根长长的猫抓板塞进一个小小的猫窝,根本塞不进去嘛!
所以,当 len_p > N 时,我们就可以确定地告诉题目,找不到这样的数,然后输出 "T_T"。
情况二:愉快的构造时间!
如果 len_p <= N,这说明我们有希望啦!我们已经有了一个 len_p 位的数 ,它满足了“是 的倍数”这个条件。现在我们只需要想办法把它“拉长”到 位就行了。
怎么能让一个数变长,又不破坏它和 的整除关系呢? 最简单的魔法就是……在它后面加 0!
每在一个整数后面加一个 0,就相当于把这个数乘以 10。例如,123 变成 1230,就是 。 如果我们把 乘以 ,就相当于在 的末尾添加了 个 0。得到的新数 显然还是 的倍数,对吧?
我们现在需要一个 位的数,而 已经占了 len_p 位。那么我们还需要补上多少位呢?很简单,就是 N - len_p 位! 所以,我们只需要在 的后面加上 N - len_p 个 0,就能得到一个符合要求的数字啦!
总结一下我们的策略:
- 读入 和 。
- 计算出 的位数,记为
len_p。 - 如果
len_p > N,说明无解,输出 "T_T"。 - 否则,先输出 ,然后紧接着输出
N - len_p个0。
这个方法是不是既简单又巧妙呀?喵~
代码实现
这是我根据上面的思路,为你精心准备的一份代码哦!注释很详细,希望能帮到你,喵~
#include <iostream>
#include <string> // 虽然我们用数字处理,但思路和字符串拼接很像
#include <cmath> // 只是为了演示另一种计算位数的方法,本代码没用
// 主人,程序从这里开始运行哦
int main() {
// 使用 std::ios::sync_with_stdio(false) 和 std::cin.tie(NULL) 可以让输入输出更快一点,喵~
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
// N 是我们期望的位数,P 是那个质数除数
long long n;
long long p;
std::cin >> n >> p;
// 我们需要计算 P 有多少位。
// 准备一个临时变量 temp_p,免得把原始的 p 给弄没了
long long temp_p = p;
int digits_in_p = 0;
// 如果 p 是 0,它是一位数。不过题目说 p 是正整数,所以这里只是个好习惯
if (temp_p == 0) {
digits_in_p = 1;
} else {
// 通过不断除以10来计算位数
// 比如 123 -> 12 -> 1 -> 0,循环3次,所以是3位数
while (temp_p > 0) {
temp_p /= 10;
digits_in_p++;
}
}
// 这是最关键的判断!
// 如果 P 本身的位数就比 N 大,那就不可能找到答案了
if (digits_in_p > n) {
std::cout << "T_T\n";
} else {
// 如果 P 的位数小于等于 N,我们就可以构造答案啦!
// 先把 P 输出
std::cout << p;
// 然后计算需要补多少个 '0'
int zeros_to_add = n - digits_in_p;
// 循环添加 '0'
for (int i = 0; i < zeros_to_add; ++i) {
std::cout << '0';
}
// 最后别忘了换行,是个好习惯哦
std::cout << '\n';
}
return 0; // 程序顺利结束,喵~
}复杂度分析
时间复杂度: 我们来分析一下时间都花在哪里了,呐。
- 计算 的位数:我们通过循环
while (temp_p > 0),每次都将temp_p除以 10。这个循环的次数大约是 以 10 为底的对数,也就是 。 - 输出结果:在最坏的情况下(比如 是个位数,而 很大),我们需要输出 个零。输出操作的次数和 是线性相关的。 所以总的时间复杂度是这两部分之和,即 。在 比较大的时候,可以近似看作 。
- 计算 的位数:我们通过循环
空间复杂度: 我们只用了几个变量(
n,p,temp_p,digits_in_p等)来存储输入和中间计算结果。这些变量占用的空间是固定的,不会随着输入规模的变大而变大,所以是常数级别的空间复杂度,喵~
知识点总结
通过这道可爱的题目,我们学会了几个小技巧呢:
- 构造性思维: 面对“请找出一个满足xx条件的数”这类问题时,不要害怕,可以试着从最简单的例子出发,通过一些简单的变换(比如乘10)来构造出满足所有条件的解。
- 数字位数计算:
while (num > 0) { num /= 10; count++; }是一个计算正整数十进制位数的经典方法,非常实用! - 整除性质: 一个数 乘以任何整数,得到的积一定能被 整除。我们正是利用了 一定是 的倍数这一性质。
- 边界条件处理: 解决问题时,一定要先考虑那些“不可能”的情况。在本题中,就是
digits_in_p > n的情况。正确处理边界是写出完美代码的关键一步哦!
希望这篇题解能帮到你,如果还有问题,随时可以再来找我哦!加油,喵~!