题解:学而思编程 特殊数字1
【题目来源】
学而思编程:特殊数字1
【题目描述】
如果一个十进制正整数能够被它的每一个非零数码整除,则称它为特殊数字,比如 \(408\) 是一个特殊数字,因为 \(408\) 能被 \(4\) 与 \(8\) 整除,而 \(1023\) 不是,因为它不能被 \(2\) 整除。给定一个正整数 \(n\),请判定它是否为特殊数字。
【输入】
第一行包含整数 \(T\),表示共有 \(T\) 组测试数据。
每组数据占一行,包含一个整数 \(n\)。
【输出】
每组数据输出一行结果,如果 \(n\) 是一个特殊数字,输出 Yes;否则,输出 No。
【输入样例】
2
102
2050
【输出样例】
Yes
Yes
【核心思想】
-
问题分析:给定一个正整数 \(n\),需要判定 \(n\) 是否能被其十进制表示中的每一个非零数码整除。这是一个数位拆分 + 整除判定问题,关键在于逐位提取数字并进行整除检验。
-
算法选择:
- 数位拆分(Digit Extraction):通过取模和整除操作逐位提取 \(n\) 的十进制数码
- 模拟验证:对每个非零数码 \(d\),检验 \(n \bmod d = 0\) 是否成立
-
关键步骤:
- 读取输入:读取测试用例数量 \(T\)
- 逐组处理(循环 \(T\) 次):
- 读取整数 \(n\)
- 数位检验:令 \(t = n\)(保留 \(n\) 的副本用于检验),当 \(t > 0\) 时循环:
- 提取最低位数码:\(a = t \bmod 10\)
- 跳过零数码:若 \(a = 0\),直接跳过(零不能作为除数)
- 整除判定:若 \(a \neq 0\) 且 \(n \bmod a \neq 0\),则 \(n\) 不是特殊数字,返回
false - 去掉已检验的最低位:\(t \leftarrow t / 10\)
- 若所有非零数码均通过检验,返回
true
- 输出结果:根据
check(n)的结果输出Yes或No
-
时间/空间复杂度:
- 时间复杂度:\(O(T \times \log_{10} n)\),每组数据需遍历 \(n\) 的所有十进制位数,位数为 \(\lfloor \log_{10} n \rfloor + 1\)
- 空间复杂度:\(O(1)\),仅使用常数个变量,无需额外数组
-
数位模拟的核心思想:
- 取模拆位:利用 \(t \bmod 10\) 获取最低位数码,\(t / 10\) 右移一位,实现 \(O(1)\) 的逐位提取
- 原数保留技巧:检验时用 \(t\) 遍历各位,但整除判定使用原始值 \(n\)(而非 \(t\)),因为 \(t\) 在拆位过程中不断变小,而检验条件要求被除数是完整的 \(n\)
- 零的特殊处理:数码 \(0\) 必须跳过,因为除数不能为零;题目定义也明确只要求被"非零数码"整除
- 短路优化:一旦发现某个数码不能整除 \(n\),立即返回
false,无需继续检验剩余位数 - 适用于数位相关判定、数字特征检验类问题
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long // 定义int为long long类型
int t; // 测试用例数量
// 检查数字x是否满足条件
bool check(int x)
{
int t = x; // 保存x的副本
while (t) // 遍历x的每一位数字
{
int a = t % 10; // 获取当前最低位数字
if (a && x % a) // 如果数字不为0且x不能被这个数字整除
{
return false; // 不满足条件
}
t /= 10; // 去掉最低位
}
return true; // 所有数字都满足条件
}
signed main() // 因为定义了#define int long long,所以用signed代替int
{
cin >> t; // 输入测试用例数量
while (t--) // 处理每个测试用例
{
int n;
cin >> n; // 输入要检查的数字
if (check(n)) // 如果满足条件
{
cout << "Yes" << endl; // 输出Yes
}
else
{
cout << "No" << endl; // 输出No
}
}
return 0; // 程序正常结束
}
【运行结果】
2
102
Yes
2050
Yes
浙公网安备 33010602011771号