找出21位的水仙数

package cn.heima;
/**
 * 找出21位的水仙数?
 * 思路:由于21位很大很大了不能用普通的循环来做
 * 分析可知无论多大的数其每一位数都是0-9的数所以我们可以反过来想
 * 1.首先我们用BigInteger来存放数
 * 2.用一个BigInteger数组来存放0^21--9^21
 * 3.再用一数组来存放0^21--9^21出现次数
 */
import java.math.BigInteger;

public class Suixianhua {
   public static void main(String[] args) {
    BigInteger[] pp =new BigInteger[10];//定义一个数组用来存放0^21-9^21
    int[] c = new int[10];//定义一个数组用来存放0^21-9^21出现的次数
    int n = 21;
    for(int i=0;i<10;i++){
        pp[i] =p(i,n);//存储0^21,1^21,2^21...到数组中
    }
    long startTime = System.currentTimeMillis();
    g(pp,c,0,0,n);//开始求解
    long endTime = System.currentTimeMillis();
    System.out.println((endTime-startTime)/1000f +"秒");
}
   public static BigInteger p(int i,int n){
        BigInteger base = BigInteger.valueOf(i);//生成一个为i的BigInteger对象
        return base.pow(n);//将BigInteger对象乘以它的n次
    }
   public static void g(BigInteger[] p,int[] c,int index ,int user,int n){
       if(index==9){//如果已经存到第9的数时
           c[9]=n - user;//它的位数为余下的位数及21-已经用的位数
           suan(c,p,n);//开始下一步计算
           return;//出栈
       }else{
           for(int i=0;i<n-user;i++){//它们出现最小次数为0---最大次数是21-前面数用的
               c[index]=i;//0,1,2,3..中在其中出现的次数
               g(p,c,index+1,user+i,n);//注意在这里user表示用了多少位所以要加i
           }
       }
   }
public static void suan(int[] c, BigInteger[] p,int n) {
    // TODO Auto-generated method stub
    int[] nb = new int[10];
    BigInteger sum = BigInteger.ZERO;//生成一个位0的BigInteger对象
    for(int i=0;i<10;i++){//sum为其和对象是重0^21-9^21的次数和其对应相乘后再相加
       sum=sum.add(p[i].multiply(BigInteger.valueOf(c[i])));
    }
    
    String ss =sum.toString();//把sum转换为string类型
    if(ss.length()!=n) return;//如果生成sum的位数没有21直接return掉
    for(int i=0;i<ss.length();i++){//如果有再统计sum0-9出现次数
        nb[ss.charAt(i)-'0']++;
    }
    for(int i=0;i<=9;i++){//如果某一位出现次数不同直接return
        if(nb[i]!=c[i])
            return;
    }
    System.out.println(ss);//能运行到这说明一切都ok输出
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值