如题,求解21位花朵数的解法,要求在3分钟之内计算完成
花朵数:N位整数,它等于各个位的数字的N次方之和,
例如有一个N位数字,a1a2a3a4.....aN = a1^N +a2^N+......aN^N要求使用java语言完成,哪个高手告诉小弟怎么解决啊~急~~~
花朵数:N位整数,它等于各个位的数字的N次方之和,
例如有一个N位数字,a1a2a3a4.....aN = a1^N +a2^N+......aN^N要求使用java语言完成,哪个高手告诉小弟怎么解决啊~急~~~
超麻烦的..
import java.util.Arrays;public class Flower {
private static int num = 21;
private static BigInteger[] table = new BigInteger[10];
private static int[] nums;
public static void main(String[] args) {
long time = System.currentTimeMillis();
for (int i = 0; i < 10; i++)
table[i] = BigInteger.valueOf(i).pow(num);
nums = new int[num];
find(nums, 0, 0);
time = System.currentTimeMillis() - time;
System.out.println(time / 1000.0 + "s");
}
public static void find(int[] nums, int level, int num) {
nums[level] = num;
if (level == nums.length - 1) {
BigInteger big = sum(nums);
int[] temp = getArray(big);
if (check(nums, temp))
System.out.println(big);
return;
}
for (int i = num; i < 10; i++)
find(nums, level + 1, i);
}
public static boolean check(int[] a1, int[] a2) {
if (a1.length != a2.length)
return false;
Arrays.sort(Arrays.copyOf(a1, a1.length));
Arrays.sort(a2);
return Arrays.equals(a1, a2);
}
public static BigInteger sum(int[] nums) {
BigInteger sum = BigInteger.ZERO;
for (int i = 0; i < nums.length; i++)
sum = sum.add(table[nums[i]]);
return sum;
}
public static int[] getArray(BigInteger big) {
String s = String.valueOf(big);
char[] ch = s.toCharArray();
int[] res = new int[ch.length];
for (int i = 0; i < ch.length; i++)
res[i] = ch[i] - '0';
return res;
}
}
应该是(1e20/21)^(1/21)大概是7.75,也就是至少有一位8或99楼这个方法的确肯定不是最好的,目前我把递归改成回溯了,算是防止栈溢出吧……import java.math.BigInteger;
import java.util.Arrays;public class Narcissistic {
private static BigInteger[] table = new BigInteger[10]; public static void main(String[] args) {
long time = System.nanoTime();
find(31);
time = System.nanoTime() - time;
System.out.println(time / 1000000000.0 + "s");
} public static void find(int n) {
for (int i = 0; i < 10; i++)
table[i] = BigInteger.valueOf(i).pow(n);
int[] nums = new int[n];
int index = 0;
int num = 0;
while (true) {
if (index < nums.length && num < 10) {
nums[index] = num;
index++;
continue;
} else if (index >= nums.length) {
BigInteger big = sum(nums);
int[] temp = getArray(big);
if (check(nums, true, temp, false))
System.out.println(big);
} else if (index <= 0) {
break;
}
index--;
num = nums[index] + 1;
}
} public static boolean check(int[] a1, boolean copy1, int[] a2, boolean copy2) {
if (a1.length != a2.length)
return false;
if (copy1)
a1 = a1.clone();
if (copy2)
a2 = a2.clone();
Arrays.sort(a1);
Arrays.sort(a2);
return Arrays.equals(a1, a2);
} public static BigInteger sum(int[] nums) {
BigInteger sum = BigInteger.ZERO;
for (int i = 0; i < nums.length; i++)
sum = sum.add(table[nums[i]]);
return sum;
} public static int[] getArray(BigInteger big) {
String s = String.valueOf(big);
int length = s.length();
int[] res = new int[length];
for (int i = 0; i < length; i++)
res[i] = s.charAt(i) - '0';
return res;
}
}
其实效率还好啦,在现在使用的电脑上21位的话50秒左右,29位是675秒,最后测试的31位大概要1212秒,貌似现在已证明最大的是39位,反正再怎么也超不过60位……
而且真的要找高位水仙花数的话……跑久点我也觉得没什么吧
import java.util.Arrays;public class Narcissistic {
private static BigInteger[] table = new BigInteger[10]; public static void main(String[] args) {
long time = System.nanoTime();
find(31);
time = System.nanoTime() - time;
System.out.println(time / 1000000000.0 + "s");
} public static void find(int n) {
for (int i = 0; i < 10; i++)
table[i] = BigInteger.valueOf(i).pow(n);
int[] nums = new int[n];
int index = 0;
int num = 0;
BigInteger sum = BigInteger.ZERO;
BigInteger MIN = BigInteger.TEN.pow(n - 1);
BigInteger MAX = BigInteger.TEN.pow(n).subtract(BigInteger.ONE);
while (true) {
if (index < nums.length && num < 10) {
BigInteger temp = sum.add(table[num]);
if (temp.compareTo(MAX) < 0) {
nums[index] = num;
index++;
sum = temp;
continue;
}
} else if (index >= nums.length && sum.compareTo(MIN) > 0) {
int[] temp = getArray(sum);
if (check(nums, true, temp, false))
System.out.println(sum);
} else if (index <= 0) {
break;
}
index--;
num = nums[index];
sum = sum.subtract(table[num]);
num++;
}
} public static boolean check(int[] a1, boolean copy1, int[] a2, boolean copy2) {
if (a1.length != a2.length)
return false;
if (copy1)
a1 = a1.clone();
if (copy2)
a2 = a2.clone();
Arrays.sort(a1);
Arrays.sort(a2);
return Arrays.equals(a1, a2);
} public static int[] getArray(BigInteger big) {
String s = String.valueOf(big);
int length = s.length();
int[] res = new int[length];
for (int i = 0; i < length; i++)
res[i] = s.charAt(i) - '0';
return res;
}
}
改进……同样环境下现在21位35-36秒,31位695秒左右……
算法很值得学习。不过2种方法都漏掉很多。第二种漏掉跟多
000--true--0--false
001--true--1--false
002--true--8--false
003--true--27--false
004--true--64--false
005--true--125--false
006--true--216--false
007--true--343--false
008--true--512--false
009--true--729--false
011--true--2--false
012--true--9--false
013--true--28--false
014--true--65--false
015--true--126--false
016--true--217--false
017--true--344--false
018--true--513--false
019--true--730--false
022--true--16--false
023--true--35--false
024--true--72--false
025--true--133--false
026--true--224--false
027--true--351--false
028--true--520--false
029--true--737--false
033--true--54--false
034--true--91--false
1)BigInteger MIN = n == 1 ? BigInteger.ZERO : BigInteger.TEN.pow(n - 1);
MIN赋值没考虑到n=1时0也是1位数,n=0时会遗漏0
2)if (temp.compareTo(MAX) <= 0) {
nums[index] = num;
index++;
sum = temp;
continue;
} else if (index <= 0) {
break;
}
判断应加上等号,n=0时会遗漏9;
最后应加上判断是否跳出循环判断,n=0时会数组越界异常(index=-1)
3) else if (index >= nums.length && sum.compareTo(MIN) >= 0) {
int[] temp = getArray(sum);
if (check(nums, true, temp, false))
System.out.println(sum);
}
判断应加上等号,n=0时会遗漏0/1
最后应加上判断是否跳出循环判断,n=0时会数组越界异常(index=-1)
3)
这里肯定用到了几个算法,
我大概可以想到的是,储存9个数的21次方以内的所有次方,保存为21*9个值 共189个
然后按照21位的递归查找,用动态规划,遍历的过程形成的结果需要记录,因为能符合条件的结果并不多,中间存储不会太高,理论上是可以算出来的,只可惜不会java,也不想用长int,尝试用 分治 把21位分成3部分,一部分7位,用3个int组成一个数来求解。
一会儿写个c#的试试。就当复习算法了
你看看赫夫曼算法吧,看完就能算了嘿嘿,看来你的数据结构学得不怎么样哈
貌似到现在为止只有我贴了代码,而且并不是简单的暴力遍历,就21位而言,#43的代码在修正后while循环一共执行了87814139次
这样的算法肯定不是最好的,但也不至于沦落到暴力遍历的程度
import java.util.Arrays;public class Narcissistic {
private static BigInteger[] table = new BigInteger[10]; public static void main(String[] args) {
long time = System.nanoTime();
find(31);
time = System.nanoTime() - time;
System.out.println(time / 1000000000.0 + "s");
} public static void find(int n) {
for (int i = 0; i < 10; i++)
table[i] = BigInteger.valueOf(i).pow(n);
int[] nums = new int[n];
int index = 0;
int num = 0;
BigInteger sum = BigInteger.ZERO;
BigInteger MIN = BigInteger.TEN.pow(n - 1);
BigInteger MAX = BigInteger.TEN.pow(n).subtract(BigInteger.ONE);
while (true) {
if (index < nums.length && num < 10) {
BigInteger temp = sum.add(table[num]);
if (temp.compareTo(MAX) < 0) {
nums[index] = num;
index++;
sum = temp;
continue;
}
} else if (index >= nums.length && sum.compareTo(MIN) > 0) {
int[] temp = getArray(sum);
if (check(nums, true, temp, false))
System.out.println(sum);
} else if (index <= 0) {
break;
}
index--;
num = nums[index];
sum = sum.subtract(table[num]);
num++;
}
} public static boolean check(int[] a1, boolean copy1, int[] a2, boolean copy2) {
if (a1.length != a2.length)
return false;
if (copy1)
a1 = a1.clone();
if (copy2)
a2 = a2.clone();
Arrays.sort(a1);
Arrays.sort(a2);
return Arrays.equals(a1, a2);
} public static int[] getArray(BigInteger big) {
String s = String.valueOf(big);
int length = s.length();
int[] res = new int[length];
for (int i = 0; i < length; i++)
res[i] = s.charAt(i) - '0';
return res;
}
}