阶乘运算——ACM

大数阶乘

时间限制:3000 ms  |  内存限制:65535 KB

难度:3

描述
我们都知道如何计算一个数的阶乘,可是,如果这个数很大呢,我们该如何去计算它并输出它?
输入
输入一个整数m(0<m<=5000)
输出
输出m的阶乘,并在输出结束之后输入一个换行符
样例输入
50
样例输出
30414093201713378043612608166064768844377641568960512000000000000

看到大数运算首先想到的是运用数组在表示大数,以前是用过int型数组,但是考虑到这将会占用大量内存。所以决定尝试 char型数组,char和int的转化很简单,(int)(n - 48)和(char)(c + 48)。然后就是解决大数的乘法问题,乘法中的难点在进位。想起来很简单,可实际上程序实现起来非常复杂,差不多用了我一下午时间,真是惭愧。下面就是程序:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define NUM 20000

int main(char argc, char**argv)
{
    char a[NUM];
    char t[NUM];
    char nstr[4];
    int i, n, oldj = 0,len = 0;
    scanf("%d", &n);

    memset(a,0,NUM*sizeof(char));
    a[0] = ‘1‘;
    memset(t,0,NUM*sizeof(char));
    t[0] = ‘1‘;

    for(i = 1; i <= n; i++)
    {
        int count = 0, lastAdd = 0, j, c = 0;
        int ii = i;
        // 拷贝字符串数组
        strcpy(a, t);
        // 整数n的转化
        while(ii)
        {
            ii/=10;
            count++;
        }
        sprintf(nstr, "%d", i);

        for(c = 0; c < count - 1; c++)
        {
            if(a[oldj + c] == ‘\0‘)
                a[oldj + c] = ‘0‘;
        }

        for(j = 0; j < NUM; j++)
        {
            int remain;
            int nn = 0, k;

            if(a[j] == ‘\0‘)
                break;

            for(k = 0; k <= j && k < count; k++)
            {
                nn += (int)(nstr[count-1-k] - 48) * (int)(a[j - k] - 48);
            }
            nn += lastAdd;
            lastAdd = nn / 10;
            remain = nn % 10;
            if(lastAdd != 0 && a[j + 1] == ‘\0‘)
                a[j + 1] = ‘0‘;
            t[j] = (char)(remain + 48);
        }
        oldj = j;
    }

    for(i = oldj-1; i >= 0; i--)
    {
        printf("%c", t[i]);
    }
    printf("\n");

    system("pause");
}

提交代码后发现还有更优的算法,而且在时间和空间上比我的程序好好几倍。瞬间感觉自己弱爆了。

#include<stdio.h>
#include<string.h>
const int maxn=20000;
int a[maxn];
int main()
{
    int n,i,j,s,c;
    scanf("%d",&n);
    memset(a,0,sizeof(a));
    a[0]=1;
    for(i=2;i<=n;i++)
    {c=0;
    for(j=0;j<=maxn;j++)
    {
    s=a[j]*i+c;
    a[j]=s%10;
    c=s/10;
    }
    }
    for(j=maxn;j>=0;j--) if(a[j]) break;
    for(i=j;i>=0;i--) printf("%d",a[i]);
    printf("\n");
    return 0;
}        

基本思路基本一致,只不过它用的是int型数组,但是为什么我的程序运行速度更慢,也许是字符和数字之间的转化太多造成的。弄巧成拙了。。

时间: 2024-07-29 08:26:24

阶乘运算——ACM的相关文章

C 数组模拟阶乘运算

#include <stdio.h> void rdump(int arr[],int len) { int i = 0; for(i=len-1;i >= 0; --i) { printf("%d",arr[i]); } printf("\n"); } void trailingZeroes(int n) { int arr[10000] = {1},len = 1,i = 0,j = 0,c = 0,d = 0; for(i=2; i <

ZOJ ACM 2022(JAVA)

题目描述请参考:ZOJ ACM 2022 1)难点分析 是大数阶乘的延伸.如果要通过计算大数阶乘的方式来计算末尾0的位数,时间效率远远无法满足2秒的要求. 2)解决方法 通过结果的规律来进行运算.设定计算N的阶乘的结果末尾为0的位数.其中N=N*(N-1)*....*i*....*1,尾数为0的尾数为zeroNumber. 首先,只有当i为5的倍数时,i*2必然个位数为0: 其次,当i为5的k次方时,i*(2的k次方) = (5*2)的k次方,所以必然末尾有k个0.由于是阶乘运算,5的k次方,必

for循环计算某个数的阶乘、阶乘和及其倒数的阶乘和

1 //4的阶乘 2 int jc = 4; //定义一个变量用来代表要计算的数值 3 long jd =1; //定义最终输出的阶乘 4 5 for(int i = 1; i <= jc;i++) //定义循环加一,从一开始不断计算,直到输入的数值为止 6 { 7 jd = jd * i; //开始进行乘法运算,并不断将前一个数的乘积赋给阶乘 8 } 9 System.out.println("阶乘为: "+jd); //输出阶乘 10 11 阶乘计算的加法形式 1 //4的阶

ACM知识点清单

本文直接来源http://blog.csdn.net/xuanandting/article/details/52160859,如有侵权,请联系删除. 训练过ACM等程序设计竞赛的人在算法上有较大的优势,这就说明当你编程能力提高之后,主要时间是花在思考算法上,不是花在写程序与debug上. 下面给个计划你练练: 第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打出来. 1.最短路(Fl

关于阶乘的两个问题

关于阶乘的两个问题 这篇介绍两个和阶乘运算相关的两个问题.切记,不可把阶乘的结果计算出来,因为会溢出.也不要转换为字符串来做,因为比较麻烦.一般而言,我们可以通过数学的方法,转化为结果和N有关,而不是N!的结果有关. 1. 计数N!末尾有几个零 给定一个N,计算N!的末端有几个零.这个问题如果把N!计算出来肯定是不现实的.像这种末尾计算有几个零,就是让你算N!的结果是10的多少倍,不是吗...类似的让你计算N!的结果的二进制形式最后又几个零,也即使让你计算N!是2的多少倍,这些问题都是相同的.

10000阶乘

public class SuperFactories { public static int lastWithUnZero = 3;// 便捷的输出测试,从几个回.为了找到一个非零元素迄今 public static void main(String[] args) { int[] factories_10000 = new int[35660];// 用数组装下阶乘的每一位 // 5的阶乘为120 factories_10000[2] = 1; factories_10000[1] = 2;

大数问题:求n的阶乘

题目:求100! 这看起来是一个非常简答的问题,递归解之毫无压力 int func(int n){ if(n <= 1) return 1; else return n*func(n-1); } 但你会发现,题目真的有这么简单吗,考虑整形数据越界没有? 这实际上是一个大数问题! 大数怎么表示呢,非常直接的.我们会想到用字符串来表示.但表示的过程中还得做阶乘运算.是不是想象的那么复杂呢? 事实上.用主要的乘法运算思想(从个位到高位逐位相乘,进位)来考虑,将暂时结果的每位与阶乘元素相乘.向高位进位.

10000的阶乘

public class SuperFactories { public static int lastWithUnZero = 3;// 方便输出测试,从后面数,找到一个非零元素为止 public static void main(String[] args) { int[] factories_10000 = new int[35660];// 用数组装下阶乘的每一位 // 5的阶乘为120 factories_10000[2] = 1; factories_10000[1] = 2; //

自己做的一个输入输出缓冲池

2014-05-15 22:02 by Jeff Li 前言 系列文章:[传送门] 马上快要期末考试了,为了学点什么.就准备这系列的博客,记录复习的成果. 正文-计数  概率 概率论研究随机事件.它源于赌徒的研究.即使是今天,概率论也常用于赌博.随机事件的结果是否只凭运气呢?高明的赌徒发现了赌博中的规律.尽管我无法预知事件的具体结果,但我可以了解每种结果出现的可能性.这是概率论的核心. "概率"到底是什么?这在数学上还有争议."频率派"认为概率是重复尝试多次,某种结