A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© kaixinkai   /  2016-2-12 12:19  /  4436 人查看  /  55 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

kaixinkai 发表于 2016-2-13 08:58
想不清楚在不能先算出结果的情况下如何边算边存,求版主指点

用数组从0开始存储1000!的结果的每位数字,先从低位算,比如定义num[2000],最初除了num[0]所有元素赋值0,然后从num[0]开始,每个数组元素都去乘1,乘2,乘3……并赋值给该数组元素,不过每次乘完后要判断是否大于10,因为我们用的是十进制,当没一位上的数大于10就会进1.。
比如。最开始,num[0]=num[0]*1 =1、num[0]=num[0]*2=2、num[0]=num[0]*3=6、、、、、、
                     当num[0]=num[0]*4=24时。因为num[0]相当于是个位。此时大于10,需要向num[1](表示十位)进位,将num[0]除以10,取十位上的2,即num[1]从0变成了2,。对num[0]此处对10求余,所以num[0]则从24变成了4..............其他位也这么来做,。应该可以算出来吧,,我记得原来做过这种大数的算法题,书上就是这么讲的。
(讲的貌似不怎么清楚,见谅。以前做的题,刚刚去看了一下,那时候是用C做的,所以要用数组来存结果,,。其实对于java,这种大数的算法题,有一个变态的方法,就是使用BigInteger类,很快就出来了。。。。)

回复 使用道具 举报 1 0
已过二十楼, 赶紧上代码吧  
回复 使用道具 举报
偶数乘以5就有零,两位数乘以五有一个或两个零.三位数有一个,两个,三个零.1000有三个零,分类一下呢,会不会好算点.

点评

答案是含有零472个,末尾零的个数为249个  发表于 2016-2-16 19:53
310个零么,, 求公布答案..  发表于 2016-2-13 23:05
啊, 不对不对, 想简单了, 果然是我数学渣啊 - -  发表于 2016-2-13 22:54
回复 使用道具 举报
挣扎了好久,觉得自己够猪脑袋得了..

QQ截图20160213231540.png (8.12 KB, 下载次数: 27)

QQ截图20160213231540.png
回复 使用道具 举报
513402004 发表于 2016-2-13 23:17
挣扎了好久,觉得自己够猪脑袋得了..

你说的这个应该是算最后有多少个零的算法
回复 使用道具 举报
酱油 发表于 2016-2-13 19:26
用数组从0开始存储1000!的结果的每位数字,先从低位算,比如定义num[2000],最初除了num[0]所有元素赋值 ...

感谢大神,在你的思想指导下结合百度终于搞出来了
回复 使用道具 举报
诚挚感谢酱油的思路指导和宋思达的热情讨论,以及各位码友的顶贴。
首先道个歉,其实发帖的时候我也没理清楚整个流程及代码。
好在功夫不负有心人,在各位码友的指点下以及度娘的帮助,终于弄出来了,老师的作业实在是变态。
下边我会贴上我结合各方网友后整理出来的代码。
回复 使用道具 举报
Hello.zip (1.09 KB, 下载次数: 91)

class Hello {
        public static void main(String[] args) {
                //System.out.println("Hello World!");
                int[] res = new int[3000];
                final int limit = 1000;
                res[1] = 1;                              //从1索引开始是为了把索引值当做结果位数使用(后边遍历结果时不遍历零即可)   
                int max_now = 1;
                for (int step = 1;step <= limit;step++) {
                        int temp = 0;
                        int now = max_now;                   //定义每一次计算结果后的位数
                        int zero = 1;
                        for (zero =0;zero <= now;zero++) { //每次乘以阶数前先跳过数组末尾的0,提高计算效率
                                if (res[zero]!=0) {
                                        break;
                                }
                        }
                        for (int carry = zero-1;carry <= now ;carry++ ) {
                                res[carry] *= step;
                                res[carry] += temp;
                                temp = 0;
                                if (res[carry] >= 0) {
                                        int carry_temp = carry;
                                        temp = res[carry];                              //temp记录当前值并加上进位值
                                        if (carry_temp <= max_now) {                    //如果当前索引小于数值位数
                                                res[carry_temp] = temp%10;                  //索引指向值模以10并赋值当前索引指向值
                                                temp/=10;                                   //temp记录除以十后的值(即十进制进位值)
                                                carry_temp++;                               //索引向前移动一位
                                        }
                                        if (carry_temp > max_now) {                     //当前索引值(即结果第一位)大于数值位数
                                                while (temp >=10) {                         //判断结果第一位是否大于10
                                                        res[carry_temp] = temp%10;              //若大于,进位
                                                        temp /= 10;
                                                        carry_temp++;
                                                }
                                                res[carry_temp] = temp;
                                                temp = 0;
                                                max_now = carry_temp;                       //并将当前索引值赋值给位数
                                        }
                                }
                        }
                }
                //System.out.println(max_now);                         //去掉注释可打印一共有多少位
                int count = 0;
                for (int j = max_now;j >0 ;j-- ) {                     //取>0是为了去掉0索引指向的值,前边注释有指出
                        //System.out.print(res[j]);                        //去掉注释可遍历数组打印每一位
                        if (res[j] == 0) {
                                count ++;
                        }
                }
                //System.out.println();                                //去掉注释即可换行,区分计算结果与含零个数
                System.out.println(count);
                //下边这段代码用于计算末尾零的个数
                /*
                int count1 = 0;
                for (int k = 1;k < max_now;k++) {
                        if (res[k] != 0) {
                                break;
                        }
                        count1++;
                }
                System.out.println(count1);
                */
        }
}


评分

参与人数 1技术分 +1 收起 理由
洋葱头头 + 1

查看全部评分

回复 使用道具 举报
楼主现在上了多少天了?
回复 使用道具 举报
答案是含有零472个,末尾零的个数为249个
一下链接中有以前的吧友用BigInteger暴力求解或其他的方法做的,有心可以做参考
http://bbs.itheima.com/forum.php?mod=viewthread&tid=132784
本帖此题的关键思想在于用基础知识模拟十进制
回复 使用道具 举报
安卓必备 发表于 2016-2-14 18:20
楼主现在上了多少天了?

年前上了半个月,年后后天开学。学到了基础班day12
回复 使用道具 举报
宋达思 发表于 2016-2-13 18:14
好高端,数学渣渣,膜拜

源码已出
回复 使用道具 举报
P神 中级黑马 2016-2-15 12:51:53
33#

好高端,数学渣渣,膜拜
回复 使用道具 举报
好久没回来了,今天才看到这个问题。感觉用大数类BigInteger暴力计算太浪费时间了,没有效率,明明是个数学题。

1000!=1*2*3*……*1000=1*(2^n1)*(3^n2)*(5^n3)……也就是小于1000的质因子的幂的乘积。要想得出结果有多少个0,其实可以转换成2的指数n1和5的指数n3的较小值,这样子问题就大大简化了,算出1到1000的每一个数值有多少个2和5然后两个数字较小的数字就是结果。那么怎么计算2和5的素因子个数呢?其实很简单:就拿2做例子,1000!中的2的方次数=[1000/2]+[1000/(2^2)]+[1000/(2^3)]+……+[1000/(2^n)]=500+250+125+62+31+15+7+3+1=994,[]为取整运算,5也是同样的方法得出结果249。所以1000!的0的个数是249。
        利用这个方法不需要大整数,只需要几个short整数和循环运算就可以高效计算,哪怕计算1亿的阶乘也拥有极高的运算效率。其实只是利用了数论的一点基础知识。

评分

参与人数 1黑马币 +2 收起 理由
洋葱头头 + 2 神马都是浮云

查看全部评分

回复 使用道具 举报
另外说一下,由于计算的算法可以明显看出,10因数分解成的2和5,由于5大于2,所以5的因子个数一定小于2的,所以只需要求解5的个数即可。如果题目复杂变成A的阶乘里有多少a*b*c*d(a<b<c<d,且都是质数)那么只需要求出A!里有多少d就可以了,结果是[A/(d)]+[A/(d^2)]+[A/(d^3)]+[A/(d^4)]+……
回复 使用道具 举报
好高端,数学渣渣,膜拜
回复 使用道具 举报
本帖最后由 姚成晖 于 2016-2-17 00:01 编辑

用数组做 只能蒙一个大概的  结果的位数   少了就不行。  果断 BigInteger
回复 使用道具 举报
本帖最后由 姚成晖 于 2016-2-17 00:06 编辑
  1. import java.math.BigInteger;

  2. public class Demo {
  3.                 /**
  4.                  *         需求:求出1000的阶层所有零和尾部零的个数
  5.                  * */
  6.         public static void main(String[] args) {
  7.                 Demo1();             //所有零的个数为472
  8.                 Demo2();             //尾部零的个数为249
  9.         }

  10.         private static void Demo2() {
  11.                 BigInteger bi1 = new BigInteger("1");
  12.                 for(int x=1;x<=1000;x++){
  13.                         BigInteger bi2 = new BigInteger(x+"");
  14.                         bi1=bi1.multiply(bi2);
  15.                         }
  16.                 String str = bi1.toString();
  17.                 int count=0;
  18.                 str = new StringBuilder(str).reverse().toString();
  19.                 for(int x=0;x<str.length()-1;x++){
  20.                         if('0'==str.charAt(x)){
  21.                                 count++;
  22.                         }else{
  23.                                 break;
  24.                         }
  25.                 }
  26.                 System.out.println(count);
  27.         }

  28.         private static void Demo1() {
  29.                 BigInteger bi1 = new BigInteger("1");
  30.                 for(int x=1;x<=1000;x++){
  31.                         BigInteger bi2 = new BigInteger(x+"");
  32.                         bi1=bi1.multiply(bi2);
  33.                 }
  34.                 String str = bi1.toString();
  35.                 int count =0;
  36.                 for(int x=0;x<str.length();x++){
  37.                         if('0'==str.charAt(x)){
  38.                                         count++;
  39.                                 }
  40.                         }
  41.                         System.out.println(count);
  42.                 }
  43. }
复制代码

评分

参与人数 1黑马币 +1 收起 理由
洋葱头头 + 1

查看全部评分

回复 使用道具 举报
zapoo 中级黑马 2016-2-17 09:21:11
39#
因为1000的阶乘太大了,int放不下,为了方便,你可以输入阶乘值在int范围内的任何数,一下是代码和运行结果
package com.java.xxx;

import java.util.Scanner;

/*
* 求1000!的结果中包含多少个0?注:1000! = 1×2×3×4×5×...×999×1000
*/
public class Test {
        public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入一个数");
                int inputNumber = sc.nextInt();
                int count = 0;
                int num1 = 1;
               
                for(int i = 1; i <= inputNumber; i++) {
                        num1 *= i;
                }
                System.out.println(inputNumber + "的阶乘结果为:" + num1);
               
                while(num1 > 0) {
                        int num = num1 % 10;
                        num1 /= 10;
                        if(num == 0) {
                                count++;
                        }
                }
                System.out.println(inputNumber + "的阶乘结果中0的个数为:" + count + "个");
        }
}

评分

参与人数 1黑马币 +1 收起 理由
洋葱头头 + 1

查看全部评分

回复 使用道具 举报
路过看看
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马