1. 题目背景与核心考察点
洛谷P10262"亲朋数"是一道经典的算法竞赛训练题目,主要考察选手对数字性质分析和基础算法实现的能力。题目要求找出特定范围内满足"亲朋数"条件的数字,这类题目在NOIP/CSP等竞赛中经常作为中等难度题出现。
亲朋数的定义是:对于一个正整数n,如果存在另一个正整数m,使得n和m的数字组成完全相同(即数字排列不同但包含相同的数字),且n能被m整除,那么n就称为亲朋数。例如122和212就是一对亲朋数,因为122÷212≈0.575(不满足),但244和122满足244÷122=2。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路分析与算法设计
2.1 暴力解法与优化方向
最直观的解法是对于每个数字n,生成所有可能的排列组合,然后检查是否存在一个排列m满足n%m==0。但这种解法的时间复杂度是O(n!),对于较大的n值完全不适用。
优化方向主要有:
- 预处理数字频率:比较数字组成是否相同可以通过统计各数字出现次数来实现
- 减少不必要的检查:当n的位数较多时,可以提前排除明显不可能的情况
- 数学性质利用:观察亲朋数的数学特征,寻找规律性
2.2 高效算法实现
采用以下步骤实现高效检查:
- 数字分解:将待检查数字n分解为各个数字,统计0-9每个数字出现的次数
- 候选数生成:生成所有可能的约数m(从1到√n)
- 数字组成比对:对每个约数m,分解其数字组成并与n比对
- 整除检查:若数字组成相同,再检查n%m==0
cpp复制bool isRelativeFriend(int n, int m) {
int countN[10] = {0};
int countM[10] = {0};
int temp = n;
while(temp > 0) {
countN[temp%10]++;
temp /= 10;
}
temp = m;
while(temp > 0) {
countM[temp%10]++;
temp /= 10;
}
for(int i=0; i<10; i++) {
if(countN[i] != count
