蓝桥杯基础练习 阶乘计算(JAVA)
问题描述
输入一个正整数n,输出n!的值。
其中n!=1*2*3*…*n。
算法描述
n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。
将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。
输入格式
输入包含一个正整数n,n<=1000。
输出格式
输出n!的准确值。
样例输入
10
样例输出
3628800
算法思路
分析题目可知,此题让求n的阶乘,就是求一直从1连乘到n的值。思路很简单,但是考虑到n如果阶乘到1000后,数值肯定会非常大,虽然java中BigInteger类可以解决大数乘法及大数加法,但是这里暂不采用,而是编写一个大数乘法和一个大数加法方法。
程序实现
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int num = input.nextInt();//要求阶乘的数num
String[] arr = new String[num+5];/用于存储各个num!结果的数组
for (int i = 1; i <= num; i++) {
if(i == 1){
arr[i] = "1";
}else{
arr[i] = mutiArr(String.valueOf(i),String.valueOf(arr[i-1]));//调用大数乘法方法
}
}
System.out.println(arr[num]);
}
//大整数加法运算方法
public static String add(String a,String b){
//当两个数的程度均不超过8位时,直接使用加法运算即可得出结果
if(a.length() <= 8 && b.length() <= 8){
return Integer.parseInt(a) + Integer.parseInt(b) + "";
}
//设置两个string类型的变量a1、a2,分别用于表示数字a的高位和低八位
String a1 = "0";
String a2 = a;
if(a.length() > 8){//当a的数字长度超过8时对a进行截取
a1 = a.substring(0,a.length()-8);//数字a的高位
a2 = a.substring(a.length()-8);//数字a的低八位
}
//与a的操作目的一样,这里不再叙述
String b1 = "0";
String b2 = b;
if(b.length() > 8){
b1 = b.substring(0,b.length()-8);//数字b的高位
b2 = b.substring(b.length()-8);//数字b的低八位
}
String t = add(a2,b2);//变量t用于存储a、b的低八位之和
while(t.length() < 8) t = "0" + t;//当t的长度不超过8时,需要在t前面补零
if(t.length() > 8) return add(add(a1,b1),"1") + t.substring(1);//当t的长度超过8时,说明低八位之和向高位有进位,所以高位a1与b1之和应再加1然后,而t应舍弃首位。
return add(a1,b1) + t;//将高位之和与低位之和拼接得出结果
}
//补零,采用递归的方法产生k个零
public static String zero(int k){
if(k == 0) return "";
if(k == 1) return "0";
int m = k / 2;
int n = k % 2;
return zero(m) + zero(m) + zero(n);//利用m + m + n = 来递归的产生指定数目的零
}
//大整数加法运算方法
public static String muti(String s1,String s2){
//当输入的s1、s2的长度均小于等于4时则采用普通乘法即可
if(s1.length() <= 4 && s2.length() <= 4){
return Integer.parseInt(s1) * Integer.parseInt(s2) + "";
}
//当s1的长度超过4
if(s1.length() > 4){
int k = s1.length() / 2;//将s1以k为分界线拆分
String a1 = s1.substring(0,k);//s1的高位
String a2 = s1.substring(k);//s1的低位
return add(muti(a1,s2)+zero(a2.length()),muti(a2,s2));//高位与s2相乘然后末尾补上s2.length()个零再与低位与
s2相乘结果相加
}
return muti(s2,s1);//当两个if均未匹配上时,说明s2长度超过4,所以交换一下s1与s2的位置
}
//大整数乘法运算的备忘录算法
public static String mutiArr(String s1,String s2){
String key = s1 + "M" + s2;
String key1 = s2 + "M" + s1;
//System.out.println(key);
Map<String,String> map = new HashMap<>();//设置map用于保存已经计算的结果,当涉及重复计算时,可直接从map中取值以减少不必要的计算
//出口
if(map.get(key) != null || map.get(key1) != null){
//System.out.println(map.get(key));
return map.get(key);
}
if(s1.length() <= 4 && s2.length() <= 4){
//System.out.println(Integer.parseInt(s1) * Integer.parseInt(s2) + "");
String temp = Integer.parseInt(s1) * Integer.parseInt(s2) + "";
map.put(key,temp);
map.put(key1,temp);
//System.out.println(map.get(key));
return temp;
}
if(s1.length() > 4){
int k = s1.length() / 2;
String a1 = s1.substring(0,k);
String a2 = s1.substring(k);
String temp = add(muti(a1,s2)+zero(a2.length()),muti(a2,s2));
map.put(key,temp);
map.put(key1,temp);
//System.out.println(map.get(key));
return temp;
}
return mutiArr(s2,s1);
}
}