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

日知己所无 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
...全文
5597 44 打赏 收藏 转发到动态 举报
写回复
用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)
水仙花数的vfp实现 时间:2009-05-08来源:编程入门网 作者:老马   本文作者“老马”为编程入门网VFP专栏作家,转载请保留这句话。   记得看过朋友的文章中有句话大致是这个意思:一个人编程的水平与实现同一目的所需的代码数量成反比。其实这句话很有道理,如果用这个观点来评价我自己,我应该是一个苍老的菜鸟,我做出来的东西勉强可用,但代码在高手看来却是惨不忍睹。我所走过的轨迹与常人大概也有所不同:计算机专业科班的可能在毕业后从事coding多年之后,当感觉自己力不从心时转行做管理或教师;而我恰恰相反,外贸专业毕业后狂热地自学了一些东西,教了几年C语言、vb、vfp及asp等课程,几乎所有的业余时间都用到了接活来做上,这一点也差不多达到了狂热的程度。不过后来发现自己似乎是走进了死胡同:我试图走进VC的世界,可是被MFC、SDK这些东西折磨得痛苦之极;当我为自己开始能用asp做些东西而沾沾自喜的时候,一个强调代码与界面分离的asp.net一天比一天时髦起来,而它的身后是一个.NET家族。更新的技术何时出现?天知道,或许就在明天。我终于开始明白,我实际并不象身边的人说的那样聪明,我也只是一个平庸的人;我终于开始明白,如果在我所从事的这个没有任何保障的“挨踢”行业继续做下去,过几年我会成为40、50人员,那时恐怕连愿意为我交社保、医保的地方都找不到了。所以现在我进入了企业,不再是教师,因为这需要很大的精力来证明自己的能力和水平;也不再为了些“水票管理”之类的东西而通宵达旦,因为这样做得到的是几个小钱,失去的却是最宝贵的健康。   今天和几个高中同学小聚了一下,或许是人岁数大了愿意回忆从前的事,或许是还有些酒意,所以有了上面的这一段话。不过我想这不应该算是牢骚,应该说是一个菜鸟对自己的可笑经历的总结。   我始终认为C语言是一个基础性的语言,以前无论是VB或VFP课,我总会要求同学自己找本谭浩强的《C程序设计》,把预处理命令、指针、结构体与共用体等几部分内容pass过去,阅读其基础部分的内容;而在课时充足的情况下,我也会经常拿C程序书中诸如“鸡兔同笼”这样有趣的题来“折磨”一下班上的同学。   而现在有些日子了,有两个高中同学总跑到我家里来。人活到老、学到老,这本是件好事,不过我还是有些苦恼。因为他们到我家里来学习,不仅不交学费,我还得管他们饭。他们问到的vfp的东西比较多,所以我打算继续把这方面的一些东西翻出来晒晒。从本文开始会探讨一下C程序书中比较经典的几个算法在VFP中实现的问题,当然纯属菜鸟之见,有没有用那可两说,得自己去分析。觉得有用的话,或许可以开拓思路、扩充您的知识面,我很高兴;觉得没用的话,您权当我是吃撑了,您能忍受我罗嗦了这么长时间,我一样很高兴,呵呵。   水仙花数的实现是一个比较经典的算法题,今天我们首先在vfp中来实现它。   首先我们了解一下什么是“水仙花数”。所谓水仙花数是指一个n位数,其各位数字立方和等于该数本身的值,例如:153=13+53+33 ,所以153是一个水仙花数。   我们来做一个简单点儿的:求解3位数的水仙花数,即100至999之间的水仙花数。很明显这个程序需要使用循环,并且从水仙花数的概念可知,其重点是求解出循环变量当前值的各位数字的值。剩下的工作就简单了,把求解出的各位数字的立方和与循环变量当前值进行比较,如果相等则说明这是一个水仙花数,输出它即可。相关说明见代码注释。本文发表于编程入门网:www.bianceng.cn   我们用表单来实现这个例子,运行时如下图:   参照上图开始我们的制作:   一、新建表单,向表单上添加一个标签控件,caption属性值设置为“显示100到999间的水仙花数”;添加两个命令按钮command1和command2,并将它们的caption属性值分别设置为“开始”和“清除”;添加一个编辑框控件Edit1,属性值均采用默认的。   二、添加事件代码:   1、“清除”按钮的click事件: thisform.edit1.value="" thisform.refresh   2、“开始”按钮的click事件: local i,a,b,c for i=100 to 999 a=int(i/100) &&百位的值等于这个三位数除以100后取整 b=int((i-100*a)/10) &&用这个三位数减去它的百位数字与100乘积, &&对得到的差除以10后进行取整,结果就是十位的值 c=i-int(i/10)*10 &&与上面原理相同,这是求个位的值 if i=a^3+b^3+c^3 &&成立说明是水仙花数并输出 thisform.edit1.value=thisform.edit1.value+str(i,5)+chr(13) &&用chr(13)换行 endif endfor

62,614

社区成员

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

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