一个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;
}
}