关键词:高精度
问题描述:
输入一个正整数n,输出n!的值。
其中n!=123*…*n。
输入格式:
输入包含一个正整数n,n<=1000。
输出格式:
输出n!的准确值。
算法描述:
n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。
将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。
解题思路:
在C++中,对数值型和字符型的空间所能存储的数值范围有限制,这道题除了考“算法描述”里的算法实现外,也考察了如何用整型数组存储一个数值较大的整数。
我跟着“算法描述”中的思路进行了实现,实现的难点是处理进位问题,即当数组中某一元素大于10时,如何实现将非个位的数值转存至高位,使得每个元素中只存储一个数值(0-9);与此同时需要注意的是,是否又新占用了数组中的空间(即n!的位数较(n-1)!的位数有所增加)。
亲测,用一个含2600个元素的整型数组即可实现对1000!的存储,如int a[MaxSize]。
注意点:
(1)在开始时需要将数组中的每个元素初始化为0,否则系统会随机为这些元素分配值。可导入库中的memset函数对数组进行初始化。
(2)存n!不一定会用到MaxSize个元素,可设置一个名为index的整型变量来标记有效的存储空间,令a[index]=-1,当程序碰到它时,即可知道这之后的元素还未用于存数。
代码实现:
#include <iostream>
#define MaxSize 2600
using namespace std;
int main()
{
int a[MaxSize];
int n;
cin>>n;
int i,j,t,temp,index=1;
for(i=2;i<MaxSize;i++)
a[i]=0;
a[0]=1;a[index]=-1;
for(i=2;i<=n;i++){
for(j=0;j<index;j++){
a[j]=a[j]*i;
}
for(j=0;j<index;j++){
t=0;
temp=a[j];
while(temp>0){
if(a[j+t]==-1){
a[j+t+1]=-1;
a[j+t]=0;
index++;
}
if(t==0)
a[j+t]=temp%10;
else
a[j+t]+=temp%10;
temp=temp/10;
t++;
}
}
}
for(i=index-1;i>=0;i--)
cout<<a[i];
cout<<endl;
return 0;
}
在最开始时,我并没用a[index]=-1来进行标记,这样运行出的代码只对100以下的阶层有效。后来分析了一下原因,存储位数的增加并不仅限于对最后一个a[j}进行进位处理时,可能在对a[j-2],a[j-1]进行进位操作时存储位数就已经于原来的j为,故对每一个a[j]都需要检查index,a[index]是否需要更新。
下面是错误的代码:
#include <iostream>
#define MaxSize 2700
using namespace std;
int main()
{
int a[MaxSize];
int n;
cin>>n;
int i,j,k,t,temp,index=1;
for(i=1;i<MaxSize;i++)
a[i]=0;
a[0]=1;
for(i=2;i<=n;i++){
for(j=0;j<index;j++){
a[j]=a[j]*i;
}
for(k=0;k<j;k++){
t=0;
temp=a[k];
while(temp>0){
if(t==0)
a[k+t]=temp%10;
else
a[k+t]+=temp%10;
temp=temp/10;
t++;
}
}
if(k==j && t>0)
index=k+t-1;
}
for(i=index-1;i>=0;i--)
cout<<a[i];
cout<<endl;
return 0;
}
输入输出样例:
input1:
1
output1:
1
input5:
50
output5:
30414093201713378043612608166064768844377641568960512000000000000
input7:
312
output7:
210202660512637835935172644211957133627043908720000167536756842728609276364870071276018632900069284700768301037938261101173961429020590768649673393745350229366900929723019237747008737725622726743681331817177398316310598929099640952146939184746561215434218580476712209164729840218710611141997608556081517114151978078529649675756198677900973955961088376590768187445187161362720223207506081889280736666374823205851569546732513468951411991741029659341762512184725306790769924064352250767773275338247678425384558165880296838989360876451983191202726095516684776830265993461760000000000000000000000000000000000000000000000000000000000000000000000000000
intput10:
1000
output10:
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
附:
memset用法示例:
(memset()方法可用于初始化整型数组和字符数组)
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int a[10];
/*初始化整型数组*/
memset(a,0,sizeof(a));
int i;
for(i=0;i<10;i++)
cout<<a[i]<<' ';
cout<<endl;
char str[30];
//char *s=str;
/*初始化字符型数组 (第一个参数可用指针代替)*/
memset(str,'G',sizeof(str));
cout<<str<<endl;
return 0;
}
运行结果: