您的位置:首页 > 其它

大数乘除(hdoj1023)

2011-03-13 16:03 218 查看
通过这题深深的理解了算法的重要性。

深深理解了算法没有绝对最优,只有相对,要针对具体情况设计相应的算法,这才是王道!

之前做死的写大数*大数,大数/大数,好不容易写出来,TLE,改成10^10进制,在自己机器上运行居然比10进制的还慢!后来发现是大数/大数出的问题,方法是用减法模拟除法,然后就悲剧了如果是像10^10/2这样很小的数,就这一个数都会TLE.

后来仔细观察其实没必要用大数*大数,大数/大数,只要大数/(小数)就行。然后10^10进制果断0MS过了。因为c[i]=c[i-1]*(4*i-2)/(i+1)

TLE的代码:

#include<iostream>
using namespace std ;

#define N 60
//every element in array is between 0 and 9
//reverse the data to restore,a0,a1,...,an-1
void mul(int *a,int *b,int *c,int lenA,int lenB,int &lenC){
int i;
lenC=lenA+lenB-1;//[lena+lenb-1,lena+lenb]
for(i=0;i<=lenC;i++)c[i]=0;//<= not < for the jugde lenD++;
for(i=0;i<lenA;i++){
for(int j=0;j<lenB;j++)c[i+j]+=a[i]*b[j];
}
for(i=0;i<lenC;i++){
if(c[i]>9){
c[i+1]+=(c[i]/10);
c[i]%=10;
}
}
i=lenC;
while(i>0&&c[i]==0)i--;
lenC=i+1;
}

//if a>=b return true;
bool compare(int *a,int *b,int lenA,int lenB){
if(lenA>lenB&&a[lenA-1]!=0)return true;//zero series
else if(lenA<lenB)return false;
else{
int i;
for(i=lenA-1;i>-1;i--){
if(a[i]>b[i])return true;
else if(a[i]<b[i])return false;
}
return true;
}
}
//a-b*10^(lenA-lenB)
//every element in array is between 0 and 9
//we assume a>=b , both a and b are positive
//reverse the data to restore,a0,a1,...,an-1
void sub(int *a,int *b,int *c,int lenA,int lenB,int &lenC){
fill(c,c+lenA,0);
int i;
for(i=0;i<lenB;i++){
c[i]+=(a[i]-b[i]);
if(c[i]<0)c[i]+=10,c[i+1]--;
}
for(i=lenB;i<lenA;i++)c[i]+=a[i];
i=lenA-1;
while(i>=1&&c[i]==0)i--;//
lenC=i+1;
}
//we assume a>=b ,both a and b are positive
//at last,the rest of a/b is in a
//we assume a>=b , both a and b are positive
//reverse the data to restore,a0,a1,...,an-1

void div(int *a,int *b,int *c,int lenA,int lenB,int &lenC){
//int &lenA用于求余数,注意a数组值是变化的!
lenC=lenA-lenB+1;
if(a[lenA-1]<b[lenB-1])lenC--;
if(lenC<=0){
lenC=1;
c[0]=0;
}
else{
fill(c,c+lenC,0);
int tmp
,len;
int i;
for(i=lenC-1;i>-1;i--){
while(compare(a+i,b,lenA-i,lenB)){//particular position handle
c[i]++;
sub(a+i,b,tmp,lenA-i,lenB,len);
memcpy(a+i,tmp,len*sizeof(int));
lenA=i;
if(len!=1||tmp[0]!=0)lenA+=len;
}
}
}
}

void itoi(int source,int *des,int &len){
len=0;
while(source){
des[len++]=source%10;
source/=10;
}
}
int c[101]
,cLen[101];
void catalan(int n){
c[0][0]=1;
cLen[0]=1;
int convert
,conLen,t
,tLen;
for(int i=1;i<=n;i++){
itoi(4*i-2,convert,conLen);
mul(convert,c[i-1],t,conLen,cLen[i-1],tLen);
itoi(i+1,convert,conLen);
div(t,convert,c[i],tLen,conLen,cLen[i]);
}
}

int main(){
catalan(100);
int n;
while(scanf("%d",&n)!=EOF){
int i;
for(i=cLen
-1;i>-1;i--)cout<<c
[i];
cout<<endl;
}
return 0;
}


0msAC的代码

#include<iostream>
using namespace std ;

#define LL __int64
#define RADIX 10000000000
//radix=LL_MAX,10位一组,LL*LL<__LL64,用LL存储
#define N 10
//reverse the data to restore,a0,a1,...,an-1
//a*=b
void mul(LL *a,int b,int &lenA){
int i;
for(i=0;i<lenA;i++)a[i]*=b;
for(i=0;i<lenA;i++){
if(a[i]>=RADIX){
a[i+1]+=(a[i]/RADIX);
a[i]%=RADIX;
}
}
if(a[lenA])lenA++;
for(i=lenA-1;i>0&&(!a[i]);i--);
lenA=i+1;
}
void div(LL *a,int b,int &lenA){
int i;
for(i=lenA-1;i>-1;i--){
if(i>0)a[i-1]+=((a[i]%b)*RADIX);
a[i]/=b;
}
for(i=lenA-1;i>0&&(!a[i]);i--);
lenA=i+1;
}
LL c[101]
;
int cLen[101];
void catalan(LL n){
c[0][0]=1;
cLen[0]=1;
for(LL i=1;i<=n;i++){
memcpy(c[i],c[i-1],cLen[i-1]*sizeof(LL));
cLen[i]=cLen[i-1];
mul(c[i],4*i-2,cLen[i]);
div(c[i],i+1,cLen[i]);
}
}

void output(LL *a,int lenA){
LL i;
LL t
;
memcpy(t,a,lenA*sizeof(LL));
printf("%I64d",a[lenA-1]);
for(i=lenA-2;i>-1;i--){
LL cnt=10;
while(t[i]){
t[i]/=10;
cnt--;
}
while(cnt--)printf("0");
printf("%I64d",a[i]);
}
}

int main(){
catalan(100);
LL n;
while(scanf("%d",&n)!=EOF){
output(c
,cLen
);
cout<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: