基础练习 阶乘计算

基础练习 阶乘计算

时间限制:1.0s 内存限制:512.0MB

问题描述
  输入一个正整数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


代码实现

import java.util.Scanner;

public class Main {
    static Scanner s = new Scanner(System.in);
    static final int MAX = 3000;

    public static void main(String[] args) {
        int n = s.nextInt();
        //long ct1 = System.currentTimeMillis();
        if (n < 0 || n > 1000) {
            return;
        }
        if (n == 0) { // 注意0!=1
            System.out.println(1);
            return;
        }
        if (n == 1) {
            System.out.println(1);
            return;
        }
        int[] A = new int[MAX];
        int[] mark = new int[MAX]; //用来标记A数组中被处理过的数据,处理过标记为1,否则为0
        A[0] = 1; // 初始化
        // k是乘数,从1-n。
        int index = 0;
        // index表示已经被用的数组下标
        for (int k = 1; k <= n; k++) {
            for (int j = 0; j <= index; j++) { // 这层循环是保证每一个数字都被c乘
                A[j] *= k;
            }
            for (int i = 0; i <= index; i++) { // 这层循环用来进行进位的处理
                if (A[i] > 9) {
                    A[i + 1] += A[i] / 10;
                    A[i] %= 10;
                    if(mark[i]==0){
                        index++;  //这里有问题,导致运算时间增加了很多
                        mark[i]=1; //添加mark来解决index的问题
                    }
                }
            }
        }
        for (int j = index; j >= 0; j--) {
            System.out.print(A[j]);
        }
        //long ct2 = System.currentTimeMillis();
        //System.out.println("\n算法总耗时:" + (ct2 - ct1) + " ms");
        //System.out.println("\n结果有:"+index+"位");
    }
}

算法思路

  1. 这题考的就是大数的阶乘,测试数据到了1000,1000阶乘的结果有2567位,算法总耗时:33 ms
  2. 这题我花了很长时间才做出来,因为在之前提交的时候,最后有2组数据不能通过,分别是997和1000,显示运算超时。百度其他人的代码,表示看不太懂,主要的问题就在于如何来计算A数组中用了几位。
  3. 使用index来记录数组A中用了几位,然后再来判断数组中的数据,是否大于9,如果大于,就进行进位处理,同时来用mark数组做标记(如:A[0]进行了进位处理后,if (mark[0] == 0) { mark[0]=1;index++; },当A[0]再次被处理时,index就不会进行自加)。
  4. 如:5!=120,在数组中存的就是0 2 1,此时index应该为3。在此过程中 n=5
  5. ①、A[0]=1,k=1;
  6. ②、A[0]=2,k=2 ③、A[0]=6,k=3
  7. ④、A[0]=24,k=4,同时进行进位处理,A[0]=4,A[1]=2,index=1(表示A数组被用了2位),mark[0]=1(表示第一位已经被处理过了);
  8. ⑤、A[0]=20,A[1]=10,k=5,然后A[0]进行进位处理,此时mark[0]=1,所以index不变,再A[1]进行进位处理,此时index++,mark[1]=1;结果是:A[0]=0,A[1]=2,A[2]=1
  9. ⑥、结果输出,从A中取出A[index] A[index-1] A[index-2]就是结果120
  10. 此算法肯定不是最好的写法,使用的辅助变量比较多,敬请各位原谅
    注:本程序原理不是很难,所以加的注释不算多,本人一向相信一个观念——不加注释的程序,不是一个好的程序。
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值