一个N位的十进制正整数,如果它的每个位上的数字的N次方的和等于这个数本身,则称其为花朵数。

例如:

当N=3时,153就满足条件,因为1^3+5^3+3^3=153,这样的数字也被称为水仙花数(其中,“^”表示乘方,5^3表示5的3次方,也就是立方)。

当N=4时,1634满足条件,因为1^4+6^4+3^4+4^4=1634.

当N=5时,92727满足条件。

实际上,对N的每个取值,可能有多个数字满足条件。

程序的任务是:求当N=21时,所有满足条件的水仙花数。注意:这个整数有21位,

它的各个位数字的21次方之和正好等于这个数本身。

如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。因为这个数字很大,请注意解法时间上的可行性。要求程序在3分钟内运行完毕。

在网上看到很多大侠用c和c++顺利的解决,而且效率还不错,由于自己本身是搞java的,于是在下面用java实现了一遍。
 思路分析:按照我们的习惯性思维,自然会想到穷举法,但事实上,这种方法的时间复杂是显而易见的,一旦程序开始运行,可能一年也难得结束。于是我们换种思维,21位数无非是由0到9这十个数组成的,我们现在要做的事用这十个数字组成21位数,然后计算每一种组合的21次方和,接下来统计和中的各个数字出现的次数是否吻合就行了。
 于是,对于大数据我们可以用java中的BigInteger来处理,免去了自己编写大数据计算函数的时间。于是,我们用九重循环,每一层循环中表示每个数可以出现0到21次,每得到一个数,就累加到sum中去,为了使算法更优化,需要紧接着判断一下sum是否超出了21位,若是就跳出结束。最后判断数据如果是21位数之内,则把得到的sum交给check去判断,check会调用count来统计0到9在sum中出现的次数,如果和循环中提供的0到9出现的频率相等则输出数据,由于在循环中我们是从小到大进行组合,所以最后得出的结果中一定是按照小到大的顺序输出的,省去了再编写排序的函数的时间,再次得到优化。下面给出完整的程序。

import java.math.*;
import java.util.HashMap;
public class Test11
{
 private int size = 0;//位数
 private BigInteger MAX = null;
 private BigInteger MIN = null;
 HashMap<String, BigInteger> hm = null;//用来存放0`9的size次方
 public Test11(int length)//构造要求的水仙花的位数
 {
  this.size = length;
  this.MAX = new BigInteger("10").pow(length).subtract(BigInteger.ONE);
  this.MIN = new BigInteger("10").pow(length - 1);
  this.hm = new HashMap<String, BigInteger>();
  for (int i = 0; i <= 9; i++)
  {
   hm.put(i + "n", new BigInteger(i + "").pow(length));
  }
 }
 public static void main(String[] args)
 {
  long start = System.currentTimeMillis();
  Test11 test = new Test11(21);
  test.find();
  long end = System.currentTimeMillis();
  long time = end - start;
  System.out.println("运行时间: " + time / 10e3 + "秒!");
 }
 public void find()
 {
  BigInteger sum = BigInteger.ZERO;
  int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9;//分别是0到9数字出现的次数
  for (a9 = 0; a9 <= this.size; a9++)
  {
   sum = sum.add(this.hm.get("9n").multiply(new BigInteger(a9 + "")));
   if (sum.compareTo(MAX) > 0)
    break;
   for (a8 = 0; a8 <= this.size - a9; a8++)
   {
    sum = sum.add(this.hm.get("8n").multiply(
      new BigInteger(a8 + "")));
    if (sum.compareTo(MAX) > 0)
     break;
    for (a7 = 0; a7 <= this.size - a9 - a8; a7++)
    {
     sum = sum.add(this.hm.get("7n").multiply(
       new BigInteger(a7 + "")));
     if (sum.compareTo(MAX) > 0)
      break;
     for (a6 = 0; a6 <= this.size - a9 - a8 - a7; a6++)
     {
      sum = sum.add(this.hm.get("6n").multiply(
        new BigInteger(a6 + "")));
      if (sum.compareTo(MAX) > 0)
       break;
      for (a5 = 0; a5 <= this.size - a9 - a8 - a7 - a6; a5++)
      {
       sum = sum.add(this.hm.get("5n").multiply(
         new BigInteger(a5 + "")));
       if (sum.compareTo(MAX) > 0)
        break;
       for (a4 = 0; a4 <= this.size - a9 - a8 - a7 - a6
         - a5; a4++)
       {
        sum = sum.add(this.hm.get("4n").multiply(
          new BigInteger(a4 + "")));
        if (sum.compareTo(MAX) > 0)
         break;
        for (a3 = 0; a3 <= this.size - a9 - a8 - a7
          - a6 - a5 - a4; a3++)
        {
         sum = sum.add(this.hm.get("3n").multiply(
           new BigInteger(a3 + "")));
         if (sum.compareTo(MAX) > 0)
          break;
         for (a2 = 0; a2 <= this.size - a9 - a8 - a7
           - a6 - a5 - a4 - a3; a2++)
         {
          sum = sum
            .add(this.hm
              .get("2n")
              .multiply(
                new BigInteger(
                  a2 + "")));
          if (sum.compareTo(MAX) > 0)
           break;
          for (a1 = 0; a1 <= this.size - a9 - a8
            - a7 - a6 - a5 - a4 - a3 - a2; a1++)
          {
           sum = sum.add(this.hm.get("1n")
             .multiply(
               new BigInteger(a1
                 + "")));
           if (sum.compareTo(MAX) > 0)
            break;
           {
            a0 = this.size - a9 - a8 - a7
              - a6 - a5 - a4 - a3
              - a2 - a1;
            if (sum.compareTo(MAX) < 0
              && sum.compareTo(MIN) > 0)
             check(sum.toString(), a0,
               a1, a2, a3, a4, a5,
               a6, a7, a8, a9);
           }
           sum = sum.subtract(this.hm
             .get("1n").multiply(
               new BigInteger(a1
                 + "")));
          }
          sum = sum
            .subtract(this.hm
              .get("2n")
              .multiply(
                new BigInteger(
                  a2 + "")));
         }
         sum = sum.subtract(this.hm.get("3n")
           .multiply(new BigInteger(a3 + "")));
        }
        sum = sum.subtract(this.hm.get("4n").multiply(
          new BigInteger(a4 + "")));
       }
       sum = sum.subtract(this.hm.get("5n").multiply(
         new BigInteger(a5 + "")));
      }
      sum = sum.subtract(this.hm.get("6n").multiply(
        new BigInteger(a6 + "")));
     }
     sum = sum.subtract(this.hm.get("7n").multiply(
       new BigInteger(a7 + "")));
    }
    sum = sum.subtract(this.hm.get("8n").multiply(
      new BigInteger(a8 + "")));
   }
   sum = sum.subtract(this.hm.get("9n").multiply(
     new BigInteger(a9 + "")));
  }
 }
 public static void check(String str, int a0, int a1, int a2, int a3,
   int a4, int a5, int a6, int a7, int a8, int a9)//判斷0到9出現的次數是否吻合sum結果中的
 {
  String temp = str;
  if (a0 == count(temp, "0") && a1 == count(temp, "1")
    && a2 == count(temp, "2") && a3 == count(temp, "3")
    && a4 == count(temp, "4") && a5 == count(temp, "5")
    && a6 == count(temp, "6") && a7 == count(temp, "7")
    && a8 == count(temp, "8") && a9 == count(temp, "9"))
   System.out.println(str);
 }
 public static int count(String str1, String str2)//統計sum中0到9出現的次數
 {
  String temp1 = str1;
  String temp2 = str2;
  int k = -1, count = 0;
  while (true)
  {
   k = temp1.indexOf(temp2, k + 1);
   if (k != -1)
    count++;
   else
    break;
  }
  return count;
 }
}