一个N位的十进制正整数,如果它的每个位上的数字的N次方的和等于这个数本身,则称其为花朵数。
例如:
当N=3时,153就满足条件,因为 1^3 + 5^3 + 3^3 = 153,这样的数字也被称为水仙花数(其中,“”表示乘方,53表示5的3次方,也就是立方)。
当N=4时,1634满足条件,因为 1^4 + 6^4 + 3^4 + 4^4 = 1634。
当N=5时,92727满足条件。
实际上,对N的每个取值,可能有多个数字满足条件。
程序的任务是:求N=21时,所有满足条件的花朵数。注意:这个整数有21位,它的各个位数字的21次方之和正好等于这个数本身。
如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。因为这个数字很大,请注意解法时间上的可行性。要求在1分钟之内运算完毕。
package Question10_19;
import java.math.BigInteger;
import java.util.Scanner;
class Question10Think2OptimizeMustRemember {
public static int size;
public static int array[]={0,1,2,3,4,5,6,7,8,9};
public static BigInteger powArray[] = new BigInteger[10]; // 记录0~9的size次方
public static int usedTimes[]=new int[10];// 记录0~9的使用次数
public static BigInteger iPowSizeMultiplyj[][]; //记录0到9中任意数字i的N次方乘以i出现的次
数j的结果(i^N*j)
public static BigInteger MAX; // size位的数字能表示的最大值
public static BigInteger MIN; // size位的数字能表示的最小值
public static void init() {// 用于初始化powArray[],MAX,MIN
15
for (int i = 0; i < 10; i++) {// 初始化powArray[]
powArray[i] = (new BigInteger("" + i)).pow(size);
}
MIN = (new BigInteger("10")).pow(size - 1); // 初始化最小值
MAX = (new BigInteger("10").pow(size).add(new BigInteger("-1")));// 初始化最大值
iPowSizeMultiplyj=new BigInteger[10][size+1]; //初始化iPowSizeMultiplyj[][]
for (int i = 0; i < 10; i++) {
iPowSizeMultiplyj[i][0]=BigInteger.valueOf(0);
for (int j = 1; j < size+1; j++) {
iPowSizeMultiplyj[i][j]=iPowSizeMultiplyj[i][j-1].add(powArray[i]);
}
}
}
public static void exhaustion(int arrayIndex,int used,BigInteger current) {
if (current.compareTo(MAX)>1) {//超过最大值,递归结束
return;
}
if(used==size){//size位全部分配完毕
if(current.compareTo(MIN)<0){ //已获得的值小于最小值
return;
}else {
String s=current+"";
int avaliableValueUsed[]=new int[10];
for (int i = 0; i < s.length(); i++) {
avaliableValueUsed[s.charAt(i)-'0']++;
}
for (int i = 0; i < 10; i++) {
if(usedTimes[i]!=avaliableValueUsed[i]){
return;
}
}
System.out.println(current);
return;
}
}
if(arrayIndex==0){
usedTimes[0]=size-used;
exhaustion(-1, size, current);
usedTimes[0]=0;
return;
16
}
if(current.add(iPowSizeMultiplyj[arrayIndex][size-used]).compareTo(MIN)<0){
return;
}
if(arrayIndex>=0){
for (int i = 0; i <= size-used; i++) {
if(current.add(iPowSizeMultiplyj[arrayIndex][i]).compareTo(MAX)>0){
return;
}
usedTimes[arrayIndex]=i;
exhaustion(arrayIndex-1,
used+i,current.add(iPowSizeMultiplyj[arrayIndex][i]));
usedTimes[arrayIndex]=0;
}
}else {
return;//1到9已分配完毕,不可再延伸了
}
}
public static void main(String[] args) {
// Scanner scanner = new Scanner(System.in);
// Question10Think2.size = scanner.nextInt();
long startTime = System.currentTimeMillis(); // 程序开始时间
Question10Think2OptimizeMustRemember.size=21;
Question10Think2OptimizeMustRemember.init();
Question10Think2OptimizeMustRemember.exhaustion(9, 0, BigInteger.valueOf(0));
long endTime = System.currentTimeMillis(); // 程序结束时间
System.out.println((endTime-startTime)/1000f+"秒"); // 运行总时
}
}
运行结果:
128468643043731391252
449177399146038697307
19.062 秒