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输出
}
}
/**
* 找出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输出
}
}