花朵数
-
这道题是水仙花数的扩展。
水仙花数是n=3
,例如1^3+5^3+3^3=153
,有多少符合这种情况。
而花朵数,是n
为很大的时候,即:求n=21
-
题目:
一个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分钟内运行
完毕。 -
初探思路:
- 计算并存储
[0~9]^21
的结果集 - 通过规律发现,n=21,则最后的结果肯定也是
21
位,21为long,已经无法存储,必须用到BigInteger
类 - 得到结果集,可以用
21个for循环
,暴力破解,把每种情况进行枚举
,并判断是否符合规则
,实际不科学。给你更好的计算机都无法解决。
- 计算并存储
-
参考资料:
视频讲解:蓝桥杯-花朵数的讲解 -
通过视频的讲解,终于明白他的思路:
- 首先重要发现:
n=3
时,153=1^3+3^3+5^3
或者3^3+5^3+1^3,...
结果一样,说明最终的结果只与出现的个数有关,与顺序无关
- 可以通过每个数字出现的次数,来判断是否符合条件。
- 可以通过模拟每个数字出现的次数,进行枚举
-
和一定为21位,否则不符合条件,要进行剪枝。
以下是完整的代码:import java.math.BigInteger; import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner cin=new Scanner(System.in); int n=cin.nextInt(); new Main().flowerNum(n); } public void flowerNum(int n){ //初始化,存储每一个的n次方 BigInteger[] bigIntegers=new BigInteger[10]; for(int i=0;i<10;i++){ bigIntegers[i]=new BigInteger((i)+""); bigIntegers[i]=bigIntegers[i].pow(n); } for(BigInteger bi:bigIntegers) System.out.println(bi); int [] nn=new int[10]; //用于记录,每一个数字出现的次数 find(bigIntegers,nn,0,0); } /* * 三个数的时候153,和跟排列的数字没有关系,只跟出现的次数有关,即:(1,3,5,的三次方),153,531,...最终的和都为153 * 找出21位的全部组合 * cur处理nn的第几位 * use,用掉了21位的多少个名额 */ public void find(BigInteger[] bigIntegers,int[] nn,int cur,int use){ //选到最后一个,剩下的就是他的,完成一次21位的情况 if(cur==9){ nn[9]=21-use; calculate(bigIntegers, nn); //计算,判断是否符合规则 return; } //这里模拟了一个名额,两个,三个...的情况 for(int i=0;i<21-use;i++){ nn[cur]=i; find(bigIntegers, nn, cur+1, use+i); } } /* * 计算所选的数,是否符合情况 * nn,存储每个数字出现的次数 */ public void calculate(BigInteger[] bigIntegers,int[] nn){ BigInteger sumBigInteger=BigInteger.ZERO; //求和 for(int i=0;i<10;i++){ sumBigInteger=sumBigInteger.add(bigIntegers[i].multiply(BigInteger.valueOf(nn[i]))); } StringBuffer sumBufferString=new StringBuffer(); //转换成字符串 sumBufferString.append(sumBigInteger); if(sumBufferString.length()!=21) //和是否为21位 return; //判断sumBigInteger各个数字出现了多少次 int[] nn2=new int[10]; for(int i=0;i<21;i++){ nn2[sumBufferString.charAt(i)-'0']++; } //测试是否与nn[]中各个对应位置数目是否相同 for(int i=0;i<10;i++){ if(nn[i]!=nn2[i]) return; } //完全符合,输出 System.out.println(sumBufferString); } }
其他资料:(鄙人尚未看懂)
21位水仙花数--只需3秒
花朵数算法--java
- 首先重要发现: