2010 水仙花数

关键字: 代码分享 杭电100题

问题描述

Problem Description

春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,他是这样定义的:

“水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3+3^3。

现在要求输出所有在m和n范围内的水仙花数。

Input

输入数据有多组,每组占一行,包括两个整数m和n(100<=m<=n<=999)。

Output

对于每个测试实例,要求输出所有在给定范围内的水仙花数,就是说,输出的水仙花数必须大于等于m,并且小于等于n,如果有多个,则要求从小到大排列在一行内输出,之间用一个空格隔开;

如果给定的范围内不存在水仙花数,则输出no;

每个测试实例的输出占一行。

Sample Input

100 120
300 380

Sample Output

no
370 371

问题分析

Problem Analyse

本题是为C语言初学者提供的。

前置知识:条件判断语句的语法和循环语句语法

Algorithm Analyse

这里讨论给出一个整数n,如何判断它是否为水仙花数的算法。

而判断一组数只要在外面加层循环就可以了。

  1. sum ← 0(0 赋值给 sum)
  2. n ← m
  3. 判断n是否为0,不是则进入下一步,否则跳到第7步
  4. sum += (n % 10)3
  5. n /= 10
  6. 重复第3步
  7. m 等于 sum 则返回1,否则返回0

至于输出的问题,完全可以再加个变量c,初始为0,每输出一个水仙花数都自增一次c++。然后在c > 0时就在数字前输出一个空格。最后判断 c > 0就只输出一个回车,否则还要输出no。

算法实现

从前面的算法很容易写出判断数m是否为水仙花数的函数:

int sxh(int m) {
  int sum = 0;
  int n = m;
  while (n) {
    sum += (n % 10)*(n % 10)*(n % 10);
    n /= 10;
  }
  return sum == m;
}

主函数直接调用就可以了。

int main(void) {
  int n, m, c;

  while (scanf("%d%d", &m, &n)) {
    for (c = 0; m <= n; m++) {
      if (sxh(m))
        printf(c++ ? " %d": "%d", m);
    }
    puts(c ? "\n" : "no\n");
  }

  return 0;
}

测试几组数据,都是对的。就这样提交。你完全可以通过本题。

但如果你有心,你会发现。其实从1->1000之间,总共也只有5个水仙花数:1 153 370 371 407。我们重复计算的只是这4个数字而已。

因为本题的数据两仅100->999。但万一有一题数据两非常庞大。而结果有像这次一样如此少。我们又该怎么办呢?

像这样的题目,算法很简单就可以实现,但优化也许需要我们花点时间去做,我们可以采用一种快速的“作弊”的方法:直接打表提交!

在比赛的时候,也许没有太多时间让我们去研究一道题目的算法。这样我们在思考其他题目的时间也可以用电脑来自动生成结果。

然后用哈希的思想,对每个输入的数据对应输出结果就可以了。当然,这是最没技术含量,但也是绝路上最有效的一颗救命稻草!

我这里讲这么多只是想让大家了解,应付比赛的着数是很多的。切不要思维定式了。

参考源码

redraiment使用Emacs Lisp批量迁移《HDU 2011-2019》
redraiment迁移《HDU 2010》