如何得到所有的“水仙花数”?

日知己所无 2014-06-21 11:25:17
加精
代码是有了
但是由于效率的原因,没有办法迅速执行完

高手帮忙优化一下吧


import java.math.*;
import java.util.*;

public class NarcissisticNumber {

public static void main(final String[] args) {
System.out.println("水仙花数列表");
for (BigInteger bigInteger = new BigInteger("0");
!bigInteger.equals(new BigInteger("115132219018763992565095597973971522402"));
bigInteger = bigInteger.add(new BigInteger("1"))) {
if (isNarcissisticNumber(bigInteger)) {
System.out.println(getDateTime() + "\t" + bigInteger);
}
}
}

/**
* 判断一个数是否为水仙花数:一个N位整数,其各位数字的N次方的和等于该数本身
*
* @param number
* @return 当输入的参数为水仙花数时返回true,否则返回false
*/
public static boolean isNarcissisticNumber(final BigInteger number) {
BigInteger sumOfDigitPower = new BigInteger("0"); // 各位数字的N次方的和
char[] digitArray = number.toString().toCharArray(); // 各位数字的数组
for (char digit : digitArray) {
sumOfDigitPower = sumOfDigitPower.add( // 求和
BigInteger.valueOf(
Character.digit(digit, 10) // 各位数字
).pow(digitArray.length) // N次方
);
}
return sumOfDigitPower.equals(number);
}

/**
* @return 返回包含当前日期和时间的字符串
*/
public static String getDateTime() {
Calendar calendar = Calendar.getInstance();
return ""
+ calendar.get(Calendar.YEAR) + "/"
+ (calendar.get(Calendar.MONTH) + 1) + "/"
+ calendar.get(Calendar.DATE) + " "
+ calendar.get(Calendar.HOUR_OF_DAY) + ":"
+ calendar.get(Calendar.MINUTE) + ":"
+ calendar.get(Calendar.SECOND) + ":"
+ calendar.get(Calendar.MILLISECOND);
}
}


这是目前的执行结果,后面的数出不来了

水仙花数列表
2014/6/21 12:18:32:22 0
2014/6/21 12:18:32:68 1
2014/6/21 12:18:32:68 2
2014/6/21 12:18:32:68 3
2014/6/21 12:18:32:68 4
2014/6/21 12:18:32:68 5
2014/6/21 12:18:32:68 6
2014/6/21 12:18:32:68 7
2014/6/21 12:18:32:68 8
2014/6/21 12:18:32:68 9
2014/6/21 12:18:32:84 153
2014/6/21 12:18:32:84 370
2014/6/21 12:18:32:84 371
2014/6/21 12:18:32:84 407
2014/6/21 12:18:32:240 1634
2014/6/21 12:18:32:349 8208
2014/6/21 12:18:32:380 9474
2014/6/21 12:18:32:939 54748
2014/6/21 12:18:33:60 92727
2014/6/21 12:18:33:61 93084
2014/6/21 12:18:33:998 548834
2014/6/21 12:18:36:63 1741725
2014/6/21 12:18:40:52 4210818
2014/6/21 12:18:49:103 9800817
2014/6/21 12:18:49:303 9926315
2014/6/21 12:19:14:473 24678050
2014/6/21 12:19:14:473 24678051
2014/6/21 12:21:5:730 88593477
2014/6/21 12:22:47:128 146511208
...全文
5647 44 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
44 条回复
切换为时间正序
请发表友善的回复…
发表回复
sichuanwww 2014-07-06
  • 打赏
  • 举报
回复
OpenMP
阳光_八月 2014-07-05
  • 打赏
  • 举报
回复
大部分都是JAVA的,怎么木有c++或者C语言的
JackBurd 2014-07-03
  • 打赏
  • 举报
回复
算法的问题,可以参看http://bbs.csdn.net/topics/360185693,@litaoye的C#程序计算21位秒杀,39位也只需5~6秒。
pigdehao 2014-07-02
  • 打赏
  • 举报
回复
我在想每次判断能否利用前一个数 这样最多只有2位会发生变化,重新计算这2位即可 比如1234567算好了,现在要算1234568 那前次的结果减去7^7再加上8^7就是新的结果 这样应该会很快吧?就是位数判断什么的要多点
825609451 2014-06-30
  • 打赏
  • 举报
回复
21位的只要30秒,楼主百度一下21为花朵数,在修改一下就可以了
walkuere 2014-06-28
  • 打赏
  • 举报
回复
最快的算法,恐怕是做一个数组递归 每次减去个位的pow(n,digits),加上pow(n+1,digits) 他们的差还可以写个inline函数来搞定 还有就是位数数量级不对直接continue掉
walkuere 2014-06-28
  • 打赏
  • 举报
回复
我以前面试的时候说自己数据结构和算法好 其实写起来也是像楼主一样的写法,楼里随便哪个人都比我高明~~~ 惭愧啊
vnvlyp 2014-06-27
  • 打赏
  • 举报
回复
引用 29 楼 lcf 的回复:
[quote=引用 3 楼 vnvlyp 的回复:] 按你这种毫不剪枝的暴力搜索的算法,把long范围内算完都几乎不可能。。更不要说BigInteger了。。 我给你稍微优化了一下,创建了一个乘方表,就不需要每次去pow了,另外使用long,速度相对快一点。 测试了一下,得到146511208可以从你的四分多降低到二十几秒。
	public static void main(String[] args) {
		long[][] table = createTable();
		for (long number = 0; number < Long.MAX_VALUE; number++) {
			if (isNarcissisticNumber(number, table)) {
				System.out.println(getTime() + "\t" + number);
			}
		}
	}
	
	public static boolean isNarcissisticNumber(long number, long[][] table) {
		long sum = 0;
		char[] digits = String.valueOf(number).toCharArray();
		int len = digits.length;
		for (char digit : digits) {
			sum += table[(int)(digit - 48)][len];
			if (sum < 0) return false;
		}
		
		return sum == number;
	}
	
	public static long[][] createTable() {
		long[][] table = new long[10][20];
		for (int i = 0; i < table.length; i++) {
			for (int j = 0; j < table[i].length; j++) {
				table[i][j] = (long)Math.pow(i, j);
			}
		}
		return table;
	}
	
	public static String getTime() {
		return new Date().toString();
	}
不知道你用的什么机器几十秒就搞定了。。。我跑了6分多钟也就到这儿。。 Fri Jun 27 11:53:38 HKT 2014 0 Fri Jun 27 11:53:38 HKT 2014 1 Fri Jun 27 11:53:38 HKT 2014 2 Fri Jun 27 11:53:38 HKT 2014 3 Fri Jun 27 11:53:38 HKT 2014 4 Fri Jun 27 11:53:38 HKT 2014 5 Fri Jun 27 11:53:38 HKT 2014 6 Fri Jun 27 11:53:38 HKT 2014 7 Fri Jun 27 11:53:38 HKT 2014 8 Fri Jun 27 11:53:38 HKT 2014 9 Fri Jun 27 11:53:38 HKT 2014 153 Fri Jun 27 11:53:38 HKT 2014 370 Fri Jun 27 11:53:38 HKT 2014 371 Fri Jun 27 11:53:38 HKT 2014 407 Fri Jun 27 11:53:38 HKT 2014 1634 Fri Jun 27 11:53:38 HKT 2014 8208 Fri Jun 27 11:53:38 HKT 2014 9474 Fri Jun 27 11:53:38 HKT 2014 54748 Fri Jun 27 11:53:38 HKT 2014 92727 Fri Jun 27 11:53:38 HKT 2014 93084 Fri Jun 27 11:53:38 HKT 2014 548834 Fri Jun 27 11:53:38 HKT 2014 1741725 Fri Jun 27 11:53:39 HKT 2014 4210818 Fri Jun 27 11:53:39 HKT 2014 9800817 Fri Jun 27 11:53:39 HKT 2014 9926315 Fri Jun 27 11:53:40 HKT 2014 24678050 Fri Jun 27 11:53:40 HKT 2014 24678051 Fri Jun 27 11:53:45 HKT 2014 88593477 Fri Jun 27 11:53:49 HKT 2014 146511208 Fri Jun 27 11:54:13 HKT 2014 472335975 Fri Jun 27 11:54:17 HKT 2014 534494836 Fri Jun 27 11:54:46 HKT 2014 912985153 Fri Jun 27 11:59:57 HKT 2014 4679307774[/quote] 我说的是跑到146511208用时几十秒,我可没说跑完long
lcf 2014-06-27
  • 打赏
  • 举报
回复
引用 3 楼 vnvlyp 的回复:
按你这种毫不剪枝的暴力搜索的算法,把long范围内算完都几乎不可能。。更不要说BigInteger了。。 我给你稍微优化了一下,创建了一个乘方表,就不需要每次去pow了,另外使用long,速度相对快一点。 测试了一下,得到146511208可以从你的四分多降低到二十几秒。
	public static void main(String[] args) {
		long[][] table = createTable();
		for (long number = 0; number < Long.MAX_VALUE; number++) {
			if (isNarcissisticNumber(number, table)) {
				System.out.println(getTime() + "\t" + number);
			}
		}
	}
	
	public static boolean isNarcissisticNumber(long number, long[][] table) {
		long sum = 0;
		char[] digits = String.valueOf(number).toCharArray();
		int len = digits.length;
		for (char digit : digits) {
			sum += table[(int)(digit - 48)][len];
			if (sum < 0) return false;
		}
		
		return sum == number;
	}
	
	public static long[][] createTable() {
		long[][] table = new long[10][20];
		for (int i = 0; i < table.length; i++) {
			for (int j = 0; j < table[i].length; j++) {
				table[i][j] = (long)Math.pow(i, j);
			}
		}
		return table;
	}
	
	public static String getTime() {
		return new Date().toString();
	}
不知道你用的什么机器几十秒就搞定了。。。我跑了6分多钟也就到这儿。。 Fri Jun 27 11:53:38 HKT 2014 0 Fri Jun 27 11:53:38 HKT 2014 1 Fri Jun 27 11:53:38 HKT 2014 2 Fri Jun 27 11:53:38 HKT 2014 3 Fri Jun 27 11:53:38 HKT 2014 4 Fri Jun 27 11:53:38 HKT 2014 5 Fri Jun 27 11:53:38 HKT 2014 6 Fri Jun 27 11:53:38 HKT 2014 7 Fri Jun 27 11:53:38 HKT 2014 8 Fri Jun 27 11:53:38 HKT 2014 9 Fri Jun 27 11:53:38 HKT 2014 153 Fri Jun 27 11:53:38 HKT 2014 370 Fri Jun 27 11:53:38 HKT 2014 371 Fri Jun 27 11:53:38 HKT 2014 407 Fri Jun 27 11:53:38 HKT 2014 1634 Fri Jun 27 11:53:38 HKT 2014 8208 Fri Jun 27 11:53:38 HKT 2014 9474 Fri Jun 27 11:53:38 HKT 2014 54748 Fri Jun 27 11:53:38 HKT 2014 92727 Fri Jun 27 11:53:38 HKT 2014 93084 Fri Jun 27 11:53:38 HKT 2014 548834 Fri Jun 27 11:53:38 HKT 2014 1741725 Fri Jun 27 11:53:39 HKT 2014 4210818 Fri Jun 27 11:53:39 HKT 2014 9800817 Fri Jun 27 11:53:39 HKT 2014 9926315 Fri Jun 27 11:53:40 HKT 2014 24678050 Fri Jun 27 11:53:40 HKT 2014 24678051 Fri Jun 27 11:53:45 HKT 2014 88593477 Fri Jun 27 11:53:49 HKT 2014 146511208 Fri Jun 27 11:54:13 HKT 2014 472335975 Fri Jun 27 11:54:17 HKT 2014 534494836 Fri Jun 27 11:54:46 HKT 2014 912985153 Fri Jun 27 11:59:57 HKT 2014 4679307774
lcf 2014-06-27
  • 打赏
  • 举报
回复
引用 30 楼 vnvlyp 的回复:
[quote=引用 29 楼 lcf 的回复:] [quote=引用 3 楼 vnvlyp 的回复:] 按你这种毫不剪枝的暴力搜索的算法,把long范围内算完都几乎不可能。。更不要说BigInteger了。。 我给你稍微优化了一下,创建了一个乘方表,就不需要每次去pow了,另外使用long,速度相对快一点。 测试了一下,得到146511208可以从你的四分多降低到二十几秒。
	public static void main(String[] args) {
		long[][] table = createTable();
		for (long number = 0; number < Long.MAX_VALUE; number++) {
			if (isNarcissisticNumber(number, table)) {
				System.out.println(getTime() + "\t" + number);
			}
		}
	}
	
	public static boolean isNarcissisticNumber(long number, long[][] table) {
		long sum = 0;
		char[] digits = String.valueOf(number).toCharArray();
		int len = digits.length;
		for (char digit : digits) {
			sum += table[(int)(digit - 48)][len];
			if (sum < 0) return false;
		}
		
		return sum == number;
	}
	
	public static long[][] createTable() {
		long[][] table = new long[10][20];
		for (int i = 0; i < table.length; i++) {
			for (int j = 0; j < table[i].length; j++) {
				table[i][j] = (long)Math.pow(i, j);
			}
		}
		return table;
	}
	
	public static String getTime() {
		return new Date().toString();
	}
不知道你用的什么机器几十秒就搞定了。。。我跑了6分多钟也就到这儿。。 Fri Jun 27 11:53:38 HKT 2014 0 Fri Jun 27 11:53:38 HKT 2014 1 Fri Jun 27 11:53:38 HKT 2014 2 Fri Jun 27 11:53:38 HKT 2014 3 Fri Jun 27 11:53:38 HKT 2014 4 Fri Jun 27 11:53:38 HKT 2014 5 Fri Jun 27 11:53:38 HKT 2014 6 Fri Jun 27 11:53:38 HKT 2014 7 Fri Jun 27 11:53:38 HKT 2014 8 Fri Jun 27 11:53:38 HKT 2014 9 Fri Jun 27 11:53:38 HKT 2014 153 Fri Jun 27 11:53:38 HKT 2014 370 Fri Jun 27 11:53:38 HKT 2014 371 Fri Jun 27 11:53:38 HKT 2014 407 Fri Jun 27 11:53:38 HKT 2014 1634 Fri Jun 27 11:53:38 HKT 2014 8208 Fri Jun 27 11:53:38 HKT 2014 9474 Fri Jun 27 11:53:38 HKT 2014 54748 Fri Jun 27 11:53:38 HKT 2014 92727 Fri Jun 27 11:53:38 HKT 2014 93084 Fri Jun 27 11:53:38 HKT 2014 548834 Fri Jun 27 11:53:38 HKT 2014 1741725 Fri Jun 27 11:53:39 HKT 2014 4210818 Fri Jun 27 11:53:39 HKT 2014 9800817 Fri Jun 27 11:53:39 HKT 2014 9926315 Fri Jun 27 11:53:40 HKT 2014 24678050 Fri Jun 27 11:53:40 HKT 2014 24678051 Fri Jun 27 11:53:45 HKT 2014 88593477 Fri Jun 27 11:53:49 HKT 2014 146511208 Fri Jun 27 11:54:13 HKT 2014 472335975 Fri Jun 27 11:54:17 HKT 2014 534494836 Fri Jun 27 11:54:46 HKT 2014 912985153 Fri Jun 27 11:59:57 HKT 2014 4679307774[/quote] 我说的是跑到146511208用时几十秒,我可没说跑完long[/quote] 眼花。。
Pandorym 2014-06-27
  • 打赏
  • 举报
回复
水仙花数只是自幂数的一种,严格来说三位数的3次幂数才成为水仙花数.. 我们可以严格来说嘛?。。
shine333 2014-06-27
  • 打赏
  • 举报
回复
楼主思路就有问题。 每次循环+1,会浪费很多不必要的判断的 比如4位数 1234,4321,2341,....一共24个,其实都是0个0,1个1,1个2,1个3,1个4,0个5,...,0个9组成的 所以,只要判断比如一个5位数,有可能是由几个0,几个1,...几个9组成的,然后,算出幂的合计,反过来看,是否匹配幂里面也是0个0,1个1,1个2,1个3,1个4,0个5,...,0个9组成的。 具体判断的时候,可以考虑用回溯法。
凨行者 2014-06-26
  • 打赏
  • 举报
回复
学习 ls高手不少啊 呵呵
huang054 2014-06-26
  • 打赏
  • 举报
回复
用组合数学比较快
yyfhz 2014-06-26
  • 打赏
  • 举报
回复
要证明存在最大的水仙花数其实也简单,对于长度为N的水仙花数K而言, 一方面有 K=a[1]*10^0+a[2]*10^1+...+a[N]*10^(N-1)>=a[N]*10^(N-1)>=10^(N-1) ........(1) 另一方面有 K=a[1]^N+a[2]^N+...+a[N]^N<=N*(9^N)=9N*9^(N-1) .......................(2) 比较(1)式和(2)就可以知道,都是关于N的指数函数,一个是以9为底,一个是以10为底,虽然(2)还有9N的倍数加成,但是当N足够大的时候还是比不上(1)的。 实际上,要(1)>(2),其实就是 10^(N-1)>9N*9^(N-1) =>(10/9)^(N-1)>9N 画一下函数图像就可以知道,y=(10/9)^x是一条向上弯曲的指数函数曲线,y=9*x是一条倾斜向上的直线,所以y=(10/9)^x迟早会追上并超过y=9*x这个函数的,而且一旦超过就再也不会回来了。假设这个交叉点的x值为A,则当N>A时(1)永远大于(2),也就不存在位数超过A的水仙花数了
laoer_2002 2014-06-26
  • 打赏
  • 举报
回复
厉害,学习
zgycsmb 2014-06-25
  • 打赏
  • 举报
回复
public static void main(String[] args) { for(int i=100;i<=999;i++) { int g,s,b; b=i/100; s=(i-b*100)/10; g=i-b*100-s*10; if(i==g*g*g+s*s*s+b*b*b) { System.out.println(i); } } }
laoer_2002 2014-06-25
  • 打赏
  • 举报
回复
学习
vnvlyp 2014-06-25
  • 打赏
  • 举报
回复
引用 20 楼 x19881216 的回复:
[quote=引用 3 楼 vnvlyp 的回复:] 按你这种毫不剪枝的暴力搜索的算法,把long范围内算完都几乎不可能。。更不要说BigInteger了。。 我给你稍微优化了一下,创建了一个乘方表,就不需要每次去pow了,另外使用long,速度相对快一点。 测试了一下,得到146511208可以从你的四分多降低到二十几秒。
	public static void main(String[] args) {
		long[][] table = createTable();
		for (long number = 0; number < Long.MAX_VALUE; number++) {
			if (isNarcissisticNumber(number, table)) {
				System.out.println(getTime() + "\t" + number);
			}
		}
	}
	
	public static boolean isNarcissisticNumber(long number, long[][] table) {
		long sum = 0;
		char[] digits = String.valueOf(number).toCharArray();
		int len = digits.length;
		for (char digit : digits) {
			sum += table[(int)(digit - 48)][len];
			if (sum < 0) return false;
		}
		
		return sum == number;
	}
	
	public static long[][] createTable() {
		long[][] table = new long[10][20];
		for (int i = 0; i < table.length; i++) {
			for (int j = 0; j < table[i].length; j++) {
				table[i][j] = (long)Math.pow(i, j);
			}
		}
		return table;
	}
	
	public static String getTime() {
		return new Date().toString();
	}
实际上你那个乘方表只需要 long[9][n]就可以了,0的n次幂总是0,可以从1开始计算[/quote] 0写进去只是为了方便程序逻辑,不然每次还要去判断是不是0,而且取下标时还要减1。 本来楼主这方法就慢得行不通,只能说能快一点就快一点了。
-江沐风- 2014-06-25
  • 打赏
  • 举报
回复
7楼应该是所有的水仙花数了吧;
加载更多回复(19)

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧