老题新解|大整数的因子
《信息学奥赛一本通》第167题:大整数的因子
题目描述:
已知正整数 k 满足 2<=k<=92<=k<=92<=k<=9,现给出长度最大为 30 位的十进制非负整数 c,求所有能整除 c 的 k。
输入:
一个非负整数 c,c 的位数不大于 30。
输出:
若存在满足 c%k==0c\%k==0c%k==0 的 k,从小到大输出所有这样的 k,相邻两个数之间用单个空格隔开;若没有这样的 k,则输出 none。
样例输入:
30
样例输出:
2 3 5 6
大家好,我是莫小特。
这篇文章给大家带来《信息学奥赛一本通》中的第 167 题:大整数的因子。
一、题目描述
题目描述:
已知正整数 k 满足 2<=k<=92<=k<=92<=k<=9,现给出长度最大为 30 位的十进制非负整数 c,求所有能整除 c 的 k。
输入:
一个非负整数 c,c 的位数不大于 30。
输出:
若存在满足 c%k==0c\%k==0c%k==0 的 k,从小到大输出所有这样的 k,相邻两个数之间用单个空格隔开;若没有这样的 k,则输出 none。
样例输入:
30
样例输出:
2 3 5 6
二、题意分析
这道题是信息学奥赛一本通练习题的第 167 题。
普通的整型除法在数值范围较小时可以直接使用 %
求余,但当整数超过 18 位时,long long
也无法存放整个数。
因此我们只能将输入的大整数视作字符串进行处理。
核心思想是:
通过模拟“手算取模”的过程:
从高位到低位逐位取出数字,累计余数,不断对 k 取模更新。
例如:
要判断 12345 是否能被 3 整除,
我们可以从左到右逐位计算余数:
当前位 | 计算公式 | 当前余数 |
---|---|---|
1 | (0×10 + 1)%3=1 | 1 |
2 | (1×10 + 2)%3=0 | 0 |
3 | (0×10 + 3)%3=0 | 0 |
4 | (0×10 + 4)%3=1 | 1 |
5 | (1×10 + 5)%3=0 | 0 |
按照样例输入对数据进行验证。 |
最后余数为 0,说明 12345 能被 3 整除。
在程序中,我们就用这个方法来判断从 k=2 到 9 的所有整除情况。
三、完成代码
使用字符数组 char c[31]
存储输入数字(最多 30 位 + 1 个结束符)。
char c[31];
scanf("%s", c+1);
c+1
代表我们让数组从下标 1 开始,方便理解第 i 位。
计算长度。
n = strlen(c+1);
这一步计算数字共有多少位。
需要枚举 9 次,从 2 遍历到 9。
for(k = 2; k <= 9; k++)
{}
接下来求模,设置一个变量 t
作为当前余数。
t = 0;
for(i = 1; i <= n; i++)
{t = t * 10 + c[i] - '0'; // 累积余数t %= k; // 对k取模
}
这段循环完成了手动计算 c % k
的过程。
最后判断输出即可,如果余数 t 等于 0,说明能整除:
if(t == 0)
{flag = 1;printf("%d ", k);
}
循环结束后,如果一个都没找到,则输出 none
:
if(flag)printf("\n");
elseprintf("none\n");
按样例测试。
符合样例输入和输出。
三、完整代码
该题的完整代码如下:
#include <cstdio>
#include <cstring>
using namespace std;char c[31];
int main()
{int n, k, flag = 0, t;scanf("%s", c + 1); // 从下标1开始存储输入n = strlen(c + 1); // 求长度for (k = 2; k <= 9; k++){t = 0; // 初始化余数for (int i = 1; i <= n; i++){t = t * 10 + c[i] - '0'; // 模拟手算取模t %= k;}if (t == 0){flag = 1;printf("%d ", k);}}if (flag)printf("\n");elseprintf("none\n");return 0;
}
四、总结
通过本题《大整数的因子》的练习,我们掌握了用字符串处理大整数并模拟取模运算的常用技巧。当原始整数超过基本整型范围(例如超过 long long
能表示的范围)时,直接把数读为字符串并按位处理,是既安全又高效的做法。
本题的核心要点与收获:
1、字符串按位处理 —— 将大整数视为字符数组,从高位到低位逐位处理,避免数值溢出问题。
2、模拟取模法 —— 使用 t = (t * 10 + 当前位数字) % k
的方式,在线性时间内计算 c % k
,该方法适用于任意大的十进制整数。
3、枚举与判断 —— 对 k
从 2 到 9 逐一枚举,分别用上面的方法判断能否整除,记录并输出满足条件的 k
。
4、输出格式处理 —— 注意当没有满足条件的 k
时输出 none
,否则按题目要求从小到大、空格分隔输出所有满足条件的 k
(结尾可以换行)。
通过这道题的训练,我们会更加熟练地在超过基本数据类型范围的问题中采用字符串与按位处理的思路,为处理其它高精度取模、比较类题目打下良好基础。
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注我哦!
如果有更好的方法也可以在评论区评论哦,我都会看哒~
我们下集见~