备考蓝桥杯(2)之21位数水仙花 java实现

方法1:
package pers.robert.lanqiaobeizhenti129;

import java.math.BigInteger;

/**
 * 10.求21位数的水仙花数
 * @author Robert
 *
 */
public class The010ShuixianhuashuDemo1 {
	  
    // 求 每个 i 的 21 次方   
    public static BigInteger p(int i){  
        BigInteger base = BigInteger.valueOf(i);  
        return base.pow(21);  
    }  
    public static void ji_suan(BigInteger[] pw,int[] nn){  
        BigInteger sum = BigInteger.ZERO;  
        for(int i=0;i<10;i++){  
            sum = sum.add(  
                    pw[i].multiply(BigInteger.valueOf(nn[i])));  
        }  
        String s = "" + sum;  
        if(s.length()!=21) return;  
        // 确定各数字出现的多少次   
        int[] nn2 = new int[10];  
        for(int i=0;i<21;i++){  
            nn2[s.charAt(i)-'0']++;  
        }  
        for(int i=0;i<10;i++){  
            if(nn[i]!=nn2[i]) return;  
        }  
        System.out.println(s);  
    }  
    public static void f(BigInteger[] pw, int[] nn, int cur, int use){  
        if(cur==9){  
            nn[9] = 21 - use;  
                ji_suan(pw,nn);  
            return;  
        }  
        // 对当前位置所有可能进行枚举   //这里不是全排列,但
        for(int i=0;i<21-use;i++){  
//System.out.println("43行时i的值:"+i);
            nn[cur] = i;  
            f(pw,nn,cur+1,use+i);  
        }  
    }  
    public static void main(String[] args){  
        long startTime = System.currentTimeMillis();    // 程序开始时间   
        BigInteger pw[] = new BigInteger[10];  
        for(int i=0;i<pw.length;i++){  
        	//p(i)求i的21次方
            pw[i] = p(i);  
        }  
        int nn[] = new int[10];  
        f(pw,nn,0,0);  
        System.out.println("OK");  
        long endTime = System.currentTimeMillis();  // 程序结束时X间   
        System.out.println((endTime-startTime)/1000f+"秒");  // 运行总时间   
    }  
}

分析:

函数入口:

     f(pw,nn,0,0);  
函数体:
    public static void f(BigInteger[] pw, int[] nn, int cur, int use){  
        if(cur==9){  
            nn[9] = 21 - use;  
                ji_suan(pw,nn);  
            return;  
        }  
        // 对当前位置所有可能进行枚举   //这里不是全排列,但
        for(int i=0;i<21-use;i++){  
//System.out.println("43行时i的值:"+i);
            nn[cur] = i;  
            f(pw,nn,cur+1,use+i);  
        }  
    }  
这里采用一个长度为10的int[]
        int nn[] = new int[10];  
package pers.robert.lanqiaobeizhenti129;

import java.math.BigInteger;

/**
 * 10.求21位数的水仙花数
 * 1^3 + 5^3+ 3^3 = 153
 * @author Robert
 *
 */
public class The010ShuixianhuashuDemo2 {

	public static int size;
	public static int array[]={0,1,2,3,4,5,6,7,8,9};
	public static BigInteger powArray[] = new BigInteger[10]; // 记录0~9的size次方
	public static int usedTimes[]=new int[10];// 记录0~9的使用次数
	public static BigInteger iPowSizeMultiplyj[][]; //记录0到9中任意数字i的N次方乘以i出现的次数j的结果(i^N*j)
	public static BigInteger MAX; // size位的数字能表示的最大值
	public static BigInteger MIN; // size位的数字能表示的最小值
	public static void init() {// 用于初始化powArray[],MAX,MIN
		for (int i = 0; i < 10; i++) {// 初始化powArray[]
			powArray[i] = (new BigInteger("" + i)).pow(size);
		}
		MIN = (new BigInteger("10")).pow(size - 1); // 初始化最小值  10^20
		MAX = (new BigInteger("10").pow(size).add(new BigInteger("-1")));// 初始化最大值10^21-1
		iPowSizeMultiplyj=new BigInteger[10][size+1];  //初始化iPowSizeMultiplyj[][]   int[10][22]
		for (int i = 0; i < 10; i++) {
			iPowSizeMultiplyj[i][0]=BigInteger.valueOf(0);
			for (int j = 1; j < size+1; j++) {
				iPowSizeMultiplyj[i][j]=iPowSizeMultiplyj[i][j-1].add(powArray[i]);
			}
		}
	}
	public static void exhaustion(int arrayIndex,int used,BigInteger current) { 
		if (current.compareTo(MAX)>1) {//超过最大值,递归结束
			return;
		}
		
		
		if(used==size){//size位全部分配完毕
			if(current.compareTo(MIN)<0){ //已获得的值小于最小值
				return;
			}else {
				String s=current+"";
				int avaliableValueUsed[]=new int[10];
				for (int i = 0; i < s.length(); i++) {
					avaliableValueUsed[s.charAt(i)-'0']++;
				}
				for (int i = 0; i < 10; i++) {
					if(usedTimes[i]!=avaliableValueUsed[i]){
						return;
					}
				}
				System.out.println(current);
				return;
			}
		}
		if(arrayIndex==0){
			usedTimes[0]=size-used;
			exhaustion(-1, size, current);
			usedTimes[0]=0;
			return;
		}
		if(current.add(iPowSizeMultiplyj[arrayIndex][size-used]).compareTo(MIN)<0){
			return;
		}
		if(arrayIndex>=0){
			for (int i = 0; i <= size-used; i++) {
				if(current.add(iPowSizeMultiplyj[arrayIndex][i]).compareTo(MAX)>0){
					return;
				}
				usedTimes[arrayIndex]=i;
				exhaustion(arrayIndex-1, used+i,current.add(iPowSizeMultiplyj[arrayIndex][i]));
				usedTimes[arrayIndex]=0;
			}
		}else {
			return;//1到9已分配完毕,不可再延伸了
		}
	}
	public static void main(String[] args) {
//		Scanner scanner = new Scanner(System.in);
//		Question10Think2.size = scanner.nextInt();
		long startTime = System.currentTimeMillis();	// 程序开始时间
		The010ShuixianhuashuDemo2.size=21;
		The010ShuixianhuashuDemo2.init();
		The010ShuixianhuashuDemo2.exhaustion(9, 0, BigInteger.valueOf(0));
		long endTime = System.currentTimeMillis();	// 程序结束时间
		System.out.println((endTime-startTime)/1000f+"秒");	// 运行总时
	}

}

来存放0-9每个数字在水仙花数里出现的个数,在这里所有的情况进行枚举,每个数字可能出现的次数都进行枚举,

 
if(cur==9){  
            nn[9] = 21 - use;  
            ji_suan(pw,nn);  
            return;  
        }  

当数组的下标到达9之后,下标为0-8的出现的次数已经确定,21-use则是下标为9出现的次数,

就可以进如

  ji_suan(pw,nn);  
           

符合清空的则直接输出

----------------------------------------------------------------------------------------------------------------------------------

方法2:

package pers.robert.lanqiaobeizhenti129;

import java.math.BigInteger;

/**
 * 10.求21位数的水仙花数
 * 1^3 + 5^3+ 3^3 = 153
 * @author Robert
 *
 */
public class The010ShuixianhuashuDemo2 {

	public static int size;
	public static int array[]={0,1,2,3,4,5,6,7,8,9};
	public static BigInteger powArray[] = new BigInteger[10]; // 记录0~9的size次方
	public static int usedTimes[]=new int[10];// 记录0~9的使用次数
	public static BigInteger iPowSizeMultiplyj[][]; //记录0到9中任意数字i的N次方乘以i出现的次数j的结果(i^N*j)
	public static BigInteger MAX; // size位的数字能表示的最大值
	public static BigInteger MIN; // size位的数字能表示的最小值
	public static void init() {// 用于初始化powArray[],MAX,MIN
		for (int i = 0; i < 10; i++) {// 初始化powArray[]
			powArray[i] = (new BigInteger("" + i)).pow(size);
		}
		MIN = (new BigInteger("10")).pow(size - 1); // 初始化最小值  10^20
		MAX = (new BigInteger("10").pow(size).add(new BigInteger("-1")));// 初始化最大值10^21-1
		iPowSizeMultiplyj=new BigInteger[10][size+1];  //初始化iPowSizeMultiplyj[][]   int[10][22]
		for (int i = 0; i < 10; i++) {
			iPowSizeMultiplyj[i][0]=BigInteger.valueOf(0);
			for (int j = 1; j < size+1; j++) {
				iPowSizeMultiplyj[i][j]=iPowSizeMultiplyj[i][j-1].add(powArray[i]);
			}
		}
	}
	public static void exhaustion(int arrayIndex,int used,BigInteger current) { 
		if (current.compareTo(MAX)>1) {//超过最大值,递归结束
			return;
		}
		
		
		if(used==size){//size位全部分配完毕
			if(current.compareTo(MIN)<0){ //已获得的值小于最小值
				return;
			}else {
				String s=current+"";
				int avaliableValueUsed[]=new int[10];
				for (int i = 0; i < s.length(); i++) {
					avaliableValueUsed[s.charAt(i)-'0']++;
				}
				for (int i = 0; i < 10; i++) {
					if(usedTimes[i]!=avaliableValueUsed[i]){
						return;
					}
				}
				System.out.println(current);
				return;
			}
		}
		if(arrayIndex==0){
			usedTimes[0]=size-used;
			exhaustion(-1, size, current);
			usedTimes[0]=0;
			return;
		}
		if(current.add(iPowSizeMultiplyj[arrayIndex][size-used]).compareTo(MIN)<0){
			return;
		}
		if(arrayIndex>=0){
			for (int i = 0; i <= size-used; i++) {
				if(current.add(iPowSizeMultiplyj[arrayIndex][i]).compareTo(MAX)>0){
					return;
				}
				usedTimes[arrayIndex]=i;
				exhaustion(arrayIndex-1, used+i,current.add(iPowSizeMultiplyj[arrayIndex][i]));
				usedTimes[arrayIndex]=0;
			}
		}else {
			return;//1到9已分配完毕,不可再延伸了
		}
	}
	public static void main(String[] args) {
//		Scanner scanner = new Scanner(System.in);
//		Question10Think2.size = scanner.nextInt();
public static void exhaustion(int arrayIndex,int used,BigInteger current) { 
		if (current.compareTo(MAX)>1) {//超过最大值,递归结束
			return;
		}
		if(used==size){//size位全部分配完毕
			if(current.compareTo(MIN)<0){ //已获得的值小于最小值
				return;
			}else {
				String s=current+"";
				int avaliableValueUsed[]=new int[10];
				for (int i = 0; i < s.length(); i++) {
					avaliableValueUsed[s.charAt(i)-'0']++;
				}
				for (int i = 0; i < 10; i++) {
					if(usedTimes[i]!=avaliableValueUsed[i]){
						return;
					}
				}
				System.out.println(current);
				return;
			}
		}
		if(arrayIndex==0){
			usedTimes[0]=size-used;
			exhaustion(-1, size, current);
			usedTimes[0]=0;
			return;
		}
		if(current.add(iPowSizeMultiplyj[arrayIndex][size-used]).compareTo(MIN)<0){
			return;
		}
		if(arrayIndex>=0){
			for (int i = 0; i <= size-used; i++) {
				if(current.add(iPowSizeMultiplyj[arrayIndex][i]).compareTo(MAX)>0){
					return;
				}
				usedTimes[arrayIndex]=i;
				exhaustion(arrayIndex-1, used+i,current.add(iPowSizeMultiplyj[arrayIndex][i]));
				usedTimes[arrayIndex]=0;
			}
		}else {
			return;//1到9已分配完毕,不可再延伸了
		}
	}

long startTime = System.currentTimeMillis(); // 程序开始时间The010ShuixianhuashuDemo2.size=21;The010ShuixianhuashuDemo2.init();The010ShuixianhuashuDemo2.exhaustion(9, 0, BigInteger.valueOf(0));long endTime = System.currentTimeMillis(); // 程序结束时间System.out.println((endTime-startTime)/1000f+"秒"); // 运行总时}}

分析:

        public static int usedTimes[]=new int[10];// 记录0~9的使用次数
	public static BigInteger iPowSizeMultiplyj[][]; //记录0到9中任意数字i的N次方乘以i出现的次数j的结果(i^N*j)

函数入口:

	The010ShuixianhuashuDemo2.exhaustion(9, 0, BigInteger.valueOf(0));
	

函数体:





 
 
        int nn[] = new int[10];  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值