当前位置:首页 > 入门组 > 1998年NOIP普及组三连击问题解析与代码详解(洛谷P1008)

1998年NOIP普及组三连击问题解析与代码详解(洛谷P1008)

2周前 (06-30)

1998年NOIP普及组三连击问题解析与代码详解(洛谷P1008) NOIP普及组  第1张

一、题目解读

1998年NOIP普及组三连击(洛谷P1008)要求寻找三个连续整数a、b、c(其中b=2a,c=3a),且这三个数的各位数字恰好组成1-9的排列(不重复且不包含0)。题目需输出符合条件的三连击组合,本质是数字组合与数位分析的典型问题。

二、解题思路

采用“枚举+验证”策略:

1. 范围枚举:从123开始至329(因3a≤999且需避免首位为0)遍历a;

2. 数位检查:定义isValid()筛除非100-999区间或含0的数字;

3. 唯一性验证:通过checkDigits()统计三数各位数字,确保1-9均出现一次。

核心逻辑利用数学关系简化计算,结合位运算提取数位,通过频次数组判断唯一性。

三、解题步骤

1. 初始化循环变量a,遍历[123,329];

2. 跳过无效a(如超出范围或含0);

3. 计算b=2a,c=3a并验证其有效性;

4. 调用checkDigits()检查三数各位数字是否覆盖1-9;

5. 满足条件则输出三连击组合。

步骤简洁高效,避免冗余计算。

四、代码与注释

#include <iostream>  
#include <cstring> // 用于memset函数  

using namespace std;  

// 检查数字是否在100-999且不含0  
bool isValid(int num) {  
    if (num < 100 || num > 999) return false;  
    while (num > 0) {  
        if (num % 10 == 0) return false;  
        num /= 10;  
    }  
    return true;  
}  

// 检查三数各位数字是否恰好为1-9各一次  
bool checkDigits(int a, int b, int c) {  
    int digits[10] = {0};  
    for (int num : {a, b, c}) {  
        while (num > 0) {  
            int digit = num % 10;  
            if (++digits[digit] > 1) return false;  
            num /= 10;  
        }  
    }  
    for (int i = 1; i <= 9; ++i) {  
        if (digits[i]!= 1) return false;  
    }  
    return true;  
}  

int main() {  
    for (int a = 123; a <= 329; ++a) {  
        if (!isValid(a)) continue;  
        int b = 2 * a;  
        int c = 3 * a;  
        if (isValid(b) && isValid(c) && checkDigits(a, b, c)) {  
            cout << a << " " << b << " " << c << endl;  
        }  
    }  
    return 0;  
}

五、总结

该解法巧妙利用数学关系减少搜索空间,结合数位分解与频次统计高效解题。代码简洁易读,适合算法竞赛新手学习枚举与数位处理的结合技巧。时间复杂度O(n),n为枚举范围(约200次循环)。


原创内容 转载请注明出处

标签: NOIP普及组
分享给朋友:

相关文章

【1999NOIP普及组】(洛谷P1016)旅行家的预算解题报告(附代码+注释)

【1999NOIP普及组】(洛谷P1016)旅行家的预算解题报告(附代码+注释)

一、题目解读题目要求解决旅行家从起点到终点(D1公里)的预算问题,需在沿途N个加油站中规划加油策略,使总费用最小化。每个加油站有不同油价和距离,汽车每升油可行驶D2公里,初始油量为C升,终点无加油站。...

NOIP2002普及组过河卒题解:动态规划解法与代码详解

NOIP2002普及组过河卒题解:动态规划解法与代码详解

一、题目解读“过河卒”是2002年NOIP普及组的经典题目(洛谷P1002),要求计算棋盘上卒从A点(0,0)到达B点(n,m)的路径条数。卒仅能向右或向下移动,但需避开马的控制点(马的位置及跳跃一步...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。