CUIT-ACM 新生训练题第一周 E

题目:

CUIT-ACM 新生训练题第一周 E_第1张图片
E题

题目大意:
求取N的阶乘 但是要注意这个结果可能是一个很大很大的数 所以要用高精度

思路:
开始做这道题知道要用高精度,所以按照常理开个数组,每个房间装0~9的元素,然后进行加法和乘法的计算。

#include
#include
#define maxn 1000
#define maxm 1000
int add[maxm][maxn], ans[maxm][maxn];
void ad(void)
{
    int i, j, k;
    add[0][0]=1;
    add[1][0]=1;
    for(i=2; i9)
            {
                add[i][j+1]++;
                add[i][j]==0;
            }
        }
    }
}
void answers(void)
{
    int i, j, k;
    ad();
    ans[0][0]=1;
    ans[1][0]=1;
    for(k=2; k9)
            {
                ans[k][i+1]+=ans[k][i]/10;
                ans[k][i]%=10;
            }
        }
        memcpy(add[k],ans[k],sizeof(ans[k]));
    }

}
int main()
{
    int n, i;
    answers();
    while(~scanf("%d", &n))
    {
        for(i=maxn-1; i>=0; i--)
        {
            if(ans[n][i]!=0)
            {
                break;
            }
        }
        for(; i>=0; i--)
        {
            printf("%d", ans[n][i]);
        }
        printf("\n");
    }
    return 0;
}

结果可想而知,因为阶乘的结果是一个炒鸡大的数,所以计算100!没问题200!也没问题,但是计算10000!就有问题了,一是数组开的太大耗内存,二是没有发挥好计算机的计算特性,导致时间慢
所以这个初步思路PASS

然后经过学习发现,原来的操作是每个房间放置0~9的元素,本质就是10进制,想要房间开得少,每个房间多装点东西不久OK,所以后来用了10000进制完成了这道题。

进制问题可以做个简单的比方 比如用1234x6,小xio生的做法是4x6=24,写4进2;3x6=18,18+2(刚才的进制)=20,写0进2;2x6=12,12+2=14,写4进1;1x6=6,6+1=7,写7;拼在一起就是7 4 0 4。这是我们都知道的,也是高精度加法的原理。现在可以换一种思维,将2个2个数看成一个整体。如 34x6=204,写04进2;12x6=72,72+2=74,写74,不进位;拼在一起就是74 04。我们发现这样也可以完成相同的计算,但这个方法本质就是100进制,满100向下一个位子进位。同理如果是1234 5678x6就可以采用10000进制,用最后的4个数x6,写出这个数字n%10000和进制n/10000;然后再用前一组4个数x6,写出要记录的这个数n1加上上一位进制n/10000再整体%10000和整体/10000就可以得到这个数和进制了 依次类推

#include
#include
#define N 10000
int a[N];
int main()
{
    int n, i, j, len;
    while(~scanf("%d", &n))
    {
        memset(a,0,sizeof(a));
        len=1;
        a[0]=1;
        for(i=1; i<=n; i++)
        {
            a[0]*=i;
            for(j=1; j=N)//最前面的房间只有满员(达到N)后才会开辟新的房间 这个while就是判断满员否
            {
                a[len]=a[len-1]/N;
                a[len-1]%=N;
                len++;//注意 所以最后先输出的是len-1!!!
            }

        }
        printf("%d",a[len-1]);//格式需要所以最先输出
        for(i=len-2;i>=0;i--)
            printf("%04d",a[i]);
        printf("\n");
    }
    return 0;
}

这个是高精度的一个很好的推广形式,希望能够掌握

你可能感兴趣的:(CUIT-ACM 新生训练题第一周 E)