北京大学acm1001题详细解答

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ln2/ln10+ln1/ln10 =trunc(1/ln10* (lnn+ln(n-1)+ln(n-2)+...........+ln3+ln2+ln1) 乘方:lg(a ^b)=trunc(lg(a^b))+1
=trunc(b*lg a )+1 =trunc(b*ln a / ln10)+1
for(i=1;i<=n-1;i++) { for(j=0;j<=lenb;j++) for(k=0;k<=lena;k++) { c[j+k]+=a[k]*b[j]; c[k+j+1]+=c[j+k]/10; c[j+k]%=10; } k--; j--; if(c[k+j+1]!=0) lenc=j+k+1; else lenc=j+k; for(j=0;j<=lenc;j++) b[j]=c[j]; lenb=lenc; memset(c,0,sizeof(c));
一般来说,我们会构造函数。 还是要注意初始化。 以及 总的位数。
高精度的除法
A÷B 精确值有两种情况: ①、A能被B整除,没有余数。 ②、A不能被B整除,对余数进行处理。首 先,我们知道,在做除法运算时,有一个 不变的量和三个变化的量,不变的量是除 数,三个变化的量分别是:被除数、商和 余数。
可以用减法代替除法运算:不断比较A[1..n] 与B[1..n]的大小,如果A[1..n]>=B[1..n] 则商C[1..n]+1→C[1..n],然后就是一个减 法过程:A[1..n]-B[1..n]→A[1..n]。
无论以何种顺序相乘,乘法次数一定为n(n-1)/2次。 (n为积的位数)
证明:
设F(n)表示乘法次数,则F(1)=0,满足题设 设k<n时,F(k)=k(k-1)/2,现在计算F(n) 设最后一次乘法计算为“k位数*(n-k)位数”,则 F(n)=F(k)+F(n-k)+k (n-k)=n(n-1)/2(与k的选择无关)
}
digit=n*digit; len=lenb+1-digit; flag=0; for(i=lenb-len;i>=0;i--)
if(b[i]!=0){flag=1;break;} if(flag==0) {
for(i=lenb;i>=lenb-len+1;i--)printf("%d",b[i]); printf("\n"); continue; } if(len==1&&b[lenb]==0) printf("."); else { for(i=lenb;i>=lenb-len+1;i--)printf("%d",b[i]); printf("."); } for(i=0;i<=lenb-len;i++) if(b[i]!=0) {temp=i;break;} for(i=lenb-len;i>=temp;i--) printf("%d",b[i]); printf("\n");
if(d[i]=='.')break; digit=lend-i; for(j=i;d[j];j++) d[j]=d[j+1]; lend=lend-1;
for(i=0;i<=lend/2;i++) {
temp=d[i];d[i]=d[lend-i]; d[lend-i]=temp; } for(i=0;d[i];i++) a[i]=d[i]-48; lena=lend; for(i=0;i<=lena;i++)b[i]=a[i]; lenb=lena;
10!=28*34*52*7
n!分解质因数的复杂度远小于nlogn,可以忽略 不计
与普通算法相比,分解质因数后,虽然因子个 数m变多了,但结果的位数n没有变,只要使用 了缓存,乘法次数还是约为n(n-1)/2次
因此,分解质因数不会变慢(这也可以通过实 践来说明)
分解质因数之后,出现了大量求乘幂的运算, 我们可以优化求乘幂的算法。这样,分解质因 数的好处就体现出来了
if (a[i]-b[i]-ncarry>=0) a[i]=a[i]-b[i]-ncarry,ncarry=0;
else a[i]=a[i]+N-b[i]-ncarry,ncarry=1;
}
高精度的乘法
For (i=0;i<=lena;i++) for (j=0;j<=lenb;j++) c[i+j]+=a[i]*b[j];
方法一:顺序连乘
5*6=30,1*1=1次乘法 30*7=210,2*1=2次乘法 210*8=1680,3*1=3次乘法
方法二:非顺序连乘
5*6=30,1*1=1次乘法 7*8=56,1*1= 1次乘法 30*56=1680,2*2=4次乘法
若“n位数*m位数=n+m位数”,则n个单精度数。
For (i=0;i<=lena+lenb;i++) { c[i+j+1]+=c[i+j]/N; c[i+j]=c[i+j]/N; }
这道题:பைடு நூலகம்
1.处理小数点问题,以及反序。 2.进行n次乘法。 3.进行输出,并加上小数点。
while(scanf("%s%d",d,&n)!=EOF) {
int a[150]={0},b[150]={0},c[150]={0}. int temp,flag,i,j,k,digit,s; int lend,lena,lenb,lenc,len; lend=strlen(d)-1; for(i=0;d[i];i++)
This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25. Input The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9. Output The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.
怎样分
设求n位数的平方需要F(n)次乘法 F(n)=F(t)+F(n-t)+t(n-t),F(1)=1 用数学归纳法,可证明F(n)恒等于n(n+1)/2 所以,无论怎样分,效率都是一样 将n位数分为一个1位数和n–1位数,这样处理比较方便
优化:
计算S=ax+kbx=(ab)xak 当k<xlogab时,采用(ab)xak比较好,
题目描述:
涉及到大数据的要求精确计算的问题是很 常见的。比如要求计算国家借款对于许多 电脑系统是一个非常繁重的任务。
本题中要求计算一个在零到一百以内的实 数的n次方(0<n<=25)。
在计算机上进行高精度计算,首先要处 理好以下几个基本问题:
1、数据的接收与存储; 2、计算结果位数的确定; 3、进位处理和借位处理; 4、商和余数的求法;
在设置了缓存的前提下,计算m个单精 度数的积,如果结果为n位数,则乘法次数 约为n(n–1)/2次,与m关系不大
设S=a1*a2*…*am,S是n位高进制数
可以把乘法的过程近似看做,先将这m个数 分为n组,每组的积仍然是一个单精度数, 最后计算后面这n个数的积。时间主要集中 在求最后n个数的积上,这时基本上满足 “n位数*m位数=n+m位数”,故乘法次数 可近似的看做n(n-1)/2次
输入和存储
运算因子超出了整型、实型能表示的范围,肯定不能直接用一个 数的形式来表示。能表示多个数的数据类型有两种:数组和字符 串。
(1)数组:每个数组元素存储1位(在优化时,这里是一个重 点!),有多少位就需要多少个数组元素; 优点:每一位都是数的形式,可以直接加减;运算时非常方便 缺点:数组不能直接输入;输入时每两位数之间必须有分隔符, 不符合数值的输入习惯;
否则采用ax+kbx更快
可以先计算两种算法的乘法次数,再解不等式, 就可以得到结论
也可以换一个角度来分析。其实,两种算法主 要差别在最后一步求积上。由于两种方法,积 的位数都是一样的,所以两个因数的差越大, 乘法次数就越小
(2)字符串:字符串的最大长度是255,可以表示255位。 优点:能直接输入输出,输入时,每两位数之间不必分隔符,符 合数值的输入习惯; 缺点:字符串中的每一位是一个字符,不能直接进行运算,必须 先将它转化为数值再进行运算;运算时非常不方便(注意‘0’的问 题)。
优化:
一个数组元素存放四位数 注意:是加减法时可以用interger,但是当
考虑k+t个单精度数相乘
a1*a2*…*ak *ak+1*…*ak+t
设a1*a2*…*ak结果为m位高进制数(假设已经
算出)
ak+1*…*ak+t结果为1位高进制数 若顺序相乘,需要t次“m位数*1位数” ,共
mt次乘法 可以先计算ak+1*…*ak+t,再一起乘,只需要
m+t次乘法
高精度的加法
ncarry=0; for (i=0;i<=len;i++) {
k=a[i]+b[i]+ncarry; a[i+1]+=k/N; ncarry=k%N; } 当最后ncarry>0时,len会变化!!
高精度的减法
先比较大小,大的为a,用一个变量记录符号。 ncarry=0; for (i=0;i<=len;i++) {
是乘法的时候,就要用int64,否则会出现越 界的情况。
还有就是:输出时对非最高位的补零处理。
另一个问题:
正序?? 逆序??
存储顺序
还有就是一定不要忘了初始化!!
计算结果位数的确定
两数之和的位数最大为较大的数的位数加1。 乘积的位数最大为两个因子的位数之和。 阶乘:lgn!=lgn+lg(n-1)+lg(n-2)...................+lg3+lg2+lg1 =lnn/ln10+ln(n-1)/ln10+ln(n-2)/ln10+................+ln3/ln10+
二分法求乘幂
a2n+1=a2n*a a2n=(an)2 其中,a是单精度数
二分法求乘幂之优化平方算法
怎样优化
(a+b)2=a2+2ab+b2 例:123452=1232*10000+452+2*123*45*100 把一个n位数分为一个t位数和一个n-t位数,再求平方
由于简单的减法速度太慢,故必须进行优 化。
设置一个位置值J,当A[1..n]>B[1..n]时, B[1..n]左移→B[0..n],j:=j+1,即令B[1..n] 增大10倍。这样就减少了减法的次数。当j>0 且A[1..n]<B[1..n]时,B[0..n]右移。
求n!
一个例子:计算5*6*7*8
高精度
00748067 张姣
Poj 1001
Description Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems.
相关文档
最新文档