hdu1042 N!

来源:互联网 发布:淘宝代理需要多少钱 编辑:程序博客网 时间:2024/05/16 11:21

题目链接

N!这个题目在算法竞赛入门经典 出现过,过程相当于模拟手算的过程(我的大数乘法也是这样的)。假使我们的现在知道(n-1)! ,那么n!=(n-1)!*n.这个也是显而易见的。

但是n!的结果十分的大,10000!差不多需要45000位数字。所以我们不能简单的使用一个基础类型去进行存储,所以我们想到了另一个东西--------数组,对,没错就是数组,我们可以模拟我们手算的方式来进行计算。

假设我们要求解7!,已知6!,手算过程如下

6!=720.

            7           2          0

    *                                7

--------------------------------

                                      0

               1        4

    4         9

------------------------------------

   5           0        4            0

这个过程相当简单,我们也就是拿7和6!的每一位相乘,然后按照位置加下来就可以了。当然写程序一般我们不会那么做,我们先将乘数与被乘数的第i位相乘得到的结果和上一次的进位结果加起来与10取模(既是求得当前位),放在存储结果的数组的第i位中,记录这次运算的进位(结果除以10就是进位结果),这样循环即可。


上面的描述可能太过于繁琐看代码好些。

        result[0]=1;//result是存储结果的数组                //我们存放的顺序是逆序的,以便于我们进位,例如6!=720,你们result存放的是 result[0]=0,result[1]=2,result[2]=7; for(int i=2;i<=n;i++)    {        int t=0;//进位结果,初始化进位为0        for(int j=0;j<MAXN;j++)        {            int temp=result[j]*i+t;//被乘数的第i位与乘数相乘加上进位的结果            result[j]=temp%10;//实际上存储的第i位的大小            t=temp/10000;//取得这次运算的进位结果        }    }//输出的时候逆序输出即可,记得处理前导零

这样做是没有问题的。但是面对hdu1042需要求10000!这么搞?我一开始使用上面的方法做,果断的TLE(超时),看了别人的一些资料后发现,还可以对上面的代码进行改进。我们可以观察,我们的result数组只存一位,那如果我们的result存的不是一位而是几位是不是会使我们的计算次数变少?怎么做?其实也就是简简单单改一下代码中mod的数和除的数。

result[0]=1;    for(int i=2;i<=n;i++)    {        int t=0;        int k=0;        for(int j=0;j<MAXN;j++)        {            int temp=result[j]*i+t;            result[j]=temp%10000;//改了这儿            t=temp/10000;//改了这儿        }    }


我们这样做为什么是正确的?其实我们也就是把一个数分成了几块来运算而已 ,第一段代码我们使用一块一位,现在我们是一块4位进行计算,进位也是一样。其实是进制的转换,我们从10进制的计算到了万进制的转换。

Q:上面提到的是4位一块,那能不能在提高欸例如6位7位?

A:可以的,分几块基于基础的数据类型,假设你使用int定义一个块,那么必须保证两个块的最大值相乘能够被一个int装起来,不会出现溢出。所以int可以装5位,如果6位和6位会超,可以选用64位整形存储。位数可达9位。


注意:注意多位存储的时候注意0的输出

贴下我的代码:

#include <iostream>#include <stdio.h>#include <cstring>using namespace std;const int MAXN=20000;int result[MAXN];void fac(int n){    memset(result,0,sizeof(result));    result[0]=1;    for(int i=2;i<=n;i++)    {        int t=0;        int k=0;        for(int j=0;j<MAXN;j++)        {            int temp=result[j]*i+t;            result[j]=temp%10000;            t=temp/10000;        }    }    int i=MAXN-1;    for(;!result[i];i--);    cout<<result[i];    for(i-=1;i>=0;i--)    {       if(result[i]<10){            cout<<"000";       }       else if(result[i]<100){            cout<<"00";       }       else if(result[i]<1000){            cout<<"0";       }       cout<<result[i];    }    cout<<endl;}int main(){    int n;    while(cin>>n)    {        fac(n);    }    return 0;}

已经ac。

如果我的这篇文中出现什么问题,欢迎批评指正。

0 0