(大数)洛谷题解-P1009 [NOIP 1998 普及组] 阶乘之和

知识点:大数

P1009 [NOIP 1998 普及组] 阶乘之和

题目描述

用高精度计算出 S=1!+2!+3!+⋯+n!(n≤50)。
其中 ! 表示阶乘,定义为 n!=n×(n−1)×(n−2)×⋯×1。例如,5!=5×4×3×2×1=120。

输入格式

一个正整数n。

输出格式

一个正整数S,表示计算结果。

输入输出样例 #1

输入 #1

3

输出 #1

9

说明/提示

【数据范围】

对于 100% 的数据,1≤n≤50。

分析

数据最大50!,可能爆出longlong的范围,考虑高精度。
下面是洛谷大佬的优雅实现,不用造高精度运算的轮子

#include<stdio.h>
int main()
{
    int i,A[1005]={0},B[1005]={0},n,j;
    scanf("%d", &n);
    A[0]=B[0]=1;
    for (i=2;i<=n;i++){
        for (j=0;j<100;j++)
            B[j]*=i;
//不用造大数轮子原因在这,阶乘递增1和for循环类似
        for (j=0;j<100;j++)
            if (B[j]>9){
                B[j+1] += B[j]/10;
                B[j]%=10;
            }
//模拟进位
        for (j=0;j<100;j++){
            A[j]+=B[j];
            if (A[j]>9) {
                A[j+1] += A[j]/10;
                A[j]%=10;
            }
        }
    }
    for (i=100;i>=0&&A[i]==0;i--);
    for (j=i;j>=0;j--) printf("%d", A[j]);
    return 0;
}

或者实现阶乘大数运算函数。
或者手动实现一般的大数运算,再进行阶乘。有两种
1.用栈模拟进出,c++挺方便,但是c的话要造一个栈
c++acwing--c++大数实现
2.用char字符串csdn-c大数实现
事实上,这里用int也是可以的,不过一般来说读取长数字串用char类型方便些,所以下面用char。挺麻烦的,这个题解纯纯记录下大数实现。

#include<stdio.h>
#include<string.h>
#define N 100
int a[N],b[N],c[N];
void set_zero(int *str1,int length){
    for(int i=0;i<length;i++){
        str1[i]=0;
    }
}
void add(char*str1,char*str2){
    set_zero(a,N);
    set_zero(b,N);
    set_zero(c,N);
    int length_1=strlen(str1);
    int length_2=strlen(str2);
    int maxlength=length_1>length_2?length_1:length_2;
    for(int i=0;i<length_1;i++)
    a[i]=str1[length_1-1-i]-'0';
    for(int i=0;i<length_2;i++)
    b[i]=str2[length_2-1-i]-'0';
    int wei=0;
    for(int i=0;i<maxlength;i++){
        c[i]=(a[i]+b[i]+wei)%10;
        wei=(a[i]+b[i]+wei)/10;
    }
    if(wei==1){
        c[maxlength]++;
    }

    for(int i=0;i<maxlength+1;i++){
        str1[i]=(char)(c[maxlength-i]+('0'));
    }
    str1[maxlength+1]='\0';
}
void mul_low(char *str1,int t){
    set_zero(a,N);
    set_zero(c,N);
    int length=strlen(str1);
    for(int i=0;i<length;i++)
    a[i]=str1[length-1-i]-'0';
    int wei=0;
    for(int i=0;i<length;i++){
        c[i]=(t*a[i]+wei)%10;
        wei=(t*a[i]+wei)/10;
    }
    if(wei>0){
    c[length]+=wei;
    length++;
    c[length]='\0';
}
    for(int i=0;i<length;i++){
        str1[i]=c[length-1-i]+('0');
    }
    str1[length]='\0';
}
void mul_high(char *str1,int t){

    char str_1[N];
    int length=strlen(str1);
    for(int i=0;i<length;i++)
        str_1[i]=str1[i];
    mul_low(str_1,t/10);
    str_1[length]='0';
    str_1[length+1]='\0';
    mul_low(str1,t%10);
    add(str1,str_1);
}
char s[N];
char temp[N];
int main(){
    int n;
    scanf("%d",&n);
    s[0]='0';
    s[1]='\0';
    temp[0]='1';
    temp[1]='\0';
    for(int i=1;i<n+1;i++){
        if(i<10)mul_low(temp,i);
        else if(i>=10)mul_high(temp,i);
        add(s,temp);
    }
    int length=strlen(s);
    int i=0;
    for(i=0;s[i]=='0';i++);
    for(int j=i;j<length;j++)
    printf("%c",s[j]);
    
}//计算出一个阶乘,进行add,并加入mul
posted @ 2025-04-09 21:17  hardestnut  阅读(162)  评论(0)    收藏  举报