(大数)洛谷题解-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

浙公网安备 33010602011771号