花朵数的研究

来源:互联网 发布:转换mobi软件 编辑:程序博客网 时间:2024/06/11 19:47

package mc;

import java.math.BigInteger;

import org.omg.PortableServer.ForwardRequestHelper;

/*
花朵数的研究

一个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位,可能不只有一个,请从小到大输出所
有符合条件的数字,每个数字占一行。
因为这个数字很大,请注意解法时间上的可行性。
*/

public class Num_of_Flowers {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  
  //0~9 每个数字的21次方
  BigInteger[] pw={p(0),p(1),p(2),p(3),p(4),p(5),p(6),p(7),p(8),p(9)};
  
  //0~9每个数字在21位位数中出现的次数
  int[] nn=new int[10];
  
  //算法核心:21个名额中:0~9每个数字出现的次数进行“大排列”
  f(pw,nn,0,0);
 }
 
 //求解核心:利用递归方式遍历所有数字出现次数的可能
 private static void f(BigInteger[] pw, int[] nn, int cur, int use) {
  // TODO Auto-generated method stub
  
  //选到了最后一个数字
  if(cur==9)
  {
   nn[9]=21-use;
   ji_suan(pw,nn);
   return;
  }
  
  //对当前位置的所有可能进行枚举
  for(int i=0;i<21-use;i++)
  {
   nn[cur]=i;
   f(pw, nn, cur+1, use+i);
  }
 }
 
 
 //传入的是0~9的各个21次方的值以及每个数字出现的次数。
 private static void ji_suan(BigInteger[] pw, int[] nn) {
  // TODO Auto-generated method stub
  //求和
  BigInteger sum=BigInteger.ZERO;
  for(int i=0;i<10;i++)
  {
   //求pw[]里面的数字值(已经求了21次方的和)在nn[]中出现的次数,然后再乘积求和
   sum=sum.add(pw[i].multiply(BigInteger.valueOf(nn[i])));
  }
  
  String s=""+sum;
  
  //如果sum的长度小于或大于21,可以直接不用做下一步考虑,直接返回。
  if(s.length()!=21) return;
  
  //确定和中各个数字出现多少次
  int[] nn2=new int[10];
  
  //统计0~9数字在结果中出现的次数
  for(int i=0;i<21;i++)
  {
   nn2[s.charAt(i)-'0']++;
  }
  
  //测试是否与nn[]中各个对应位置数目相同
  for(int i=0;i<10;i++)
  {
   if(nn[i]!=nn2[i])return;
  }
  
  //完全匹配!打印结果
  System.out.println(s);
 }

 //求x的21次方
 private static BigInteger p(int x) {
  // TODO Auto-generated method stub
  BigInteger base=BigInteger.ONE;
  
  for(int i=0;i<21;i++)
  {
   base=base.multiply(BigInteger.valueOf(x));
  }
  
  return base;
 }

}