本文总结ACM大数问题的概念与常用算法
大数是指计算的数值非常大或者对运算的精度要求非常高,用已知的数据类型无法表示的数值。
1、整型
Short : 16位整数,占两个字节,-2^15——2^15-1 (-32768 —— 32768)
Unsigned short : 占2个字节, 0——2^16 (0——65535)
Int : 32位整数,占4个字节,-2^31——2^31-1
Unsigned int : 占四个字节,0 —— 2^31-1
Long == int(由于现在使用的都是32位系统)
2、VC的64位整数
__int64: 占8字节,-2^63 —— 2^63-1
Unsigned __int64: 占8字节,0——2^64-1
3、G++的64位整数
Long long == __int64
Unsigned long long == unsigned __int64
4、实数
Float:占四个字节,7位有效数字
Double: 占8个字节,15位有效数字
浮点型的问题都是追求精度的,在一般情况下我们应当选择使用double,而很少用float.
5、基本的思想是:用数组存放和表示大整数。一个数组元素存放大整数中的一位
大数运算的方法
6、用数组来模拟大数的运算(加、减、乘、除、任意精度计算)
1.大数加法
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
void add(char *a,char *b,char *back)
{int i,j,k,up,x,y,z,l;
char *c;
if(strlen(a)>strlen(b)) l=strlen(a)+2;//可能有进位
else l=strlen(b)+2;
c=(char *) malloc(l*sizeof(char));
i=strlen(a)-1;j=strlen(b)-1;k=0; up=0;
while(i>=0||j>=0)
{if(i<0) x=’0′;else x=a[i];
if(j<0) y=’0′;else y=b[j];
z=x-‘0’+y-‘0’;//在相同的位置的数相加
if(up) z+=1;//up表示进位
if(z>9) {up=1;z%=10;} else up=0;
c[k++]=z+’0′;
i–;j–;
}
if(up) c[k++]=’1′;
i=0;c[k]=’\0′;
for(k-=1;k>=0;k–)back[i++]=c[k];//保存结果在back[]数组中
back[i]=’\0′;
}
int main()
{int i;
char a[201],b[201],c[210];
cin>>a>>b;add(a,b,c);
for(i=0;c[i]!=’\0′;i++)
printf(“%c”,c[i]);
printf(“\n”);
return 0;
}
2.大数乘法
#include <stdio.h>
#include <string.h>
#define N 100
#define M 1000
void mult(char a[],char b[],char s[])
{ int i,j,k=0,alen,blen,sum=0,res[M][N]={0},flag=0;
char result[N*N];
alen=strlen(a); blen=strlen(b);
for (i=0;i<alen;i++)
for (j=0;j<blen;j++)
res[i][j]=(a[i]-‘0’)*(b[j]-‘0’);
for (i=alen–1;i>=0;i–)
{ for (j=blen–1;j>=0;j–)
sum=sum+res[i+blen–j–1][j];
result[k]=sum%10; k=k+1; sum=sum/10;
}
for (i=blen–2;i>=0;i–)
{ for (j=0;j<=i;j++)
sum=sum+res[i–j][j];
result[k]=sum%10; k=k+1; sum=sum/10;
}
if (sum!=0) { result[k]=sum; k=k+1;}
for (i=0;i<k;i++) result[i]+=‘0’;
for (i=k–1;i>=0;i–) s[i]=result[k–1–i];
s[k]=‘\0’;
while(1)
{ if (strlen(s)!=strlen(a)&&s[0]==‘0’) strcpy(s,s+1);
else break;
}
}
int main()
{ char a[20],b[1000],c[1000];
int n,i;
scanf(“%s%d”,a,&n);
strcpy(b,a);
for (i=2;i<=n; i++)
{ mult(b,a,c); strcpy(b,c); }
printf(“%s\n”,c);
return 0;
}
3.大数减法
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
void sub(char s1[],char s2[],char t[])
{
int i,l2,l1,k;
l2=strlen(s2);l1=strlen(s1);
t[l1]=’\0′;l1–;
for (i=l2-1;i>=0;i–,l1–)
{if (s1[l1]-s2[i]>=0)t[l1]=s1[l1]-s2[i]+’0′;
else
{t[l1]=10+s1[l1]-s2[i]+’0′;
s1[l1-1]=s1[l1-1]-1;
}
}
k=l1;
while(s1[k]<0) {s1[k]+=10;s1[k-1]-=1;k–;}
while(l1>=0) {t[l1]=s1[l1];l1–;}
loop:
if (t[0]==’0′)
{l1=strlen(s1);
for (i=0;i<l1-1;i++) t[i]=t[i+1];t[l1-1]=’\0′;
goto loop;
}
if (strlen(t)==0) {t[0]=’0′;t[1]=’\0′;}
}
int main()
{
int n;
char a[100],b[100],c[100];
cin>>n;
while(n–)
{cin>>a>>b;
sub(a,b,c);
cout<<c<<endl;
}
return 0;
}