- #include<stdio.h>
- #include<memory.h>
- #include<math.h>
- #include<assert.h>
- #include<string.h>
- #include<malloc.h>
- #include<time.h>
- int max(int x,int y)
- {
- return x>y?x:y;
- }
- typedef struct
- {
- int *NumHead;
- int size;
- }BigNumber;
- const size_t BigSize=sizeof(BigNumber);
- /*********************************************************************************/
- /******************* 思想 **********************/
- /* int n=31*log2 即表示一个int型整数表示成十进制需要n位,n计算得9 */
- /* 因此,可设进制为10^9,但因为base^2<=10^9,所以BigBase=10^4
- 输出时转换成十进制在每个元素后面加相应位数的0即可 */
- /********************************************************************************/
- const int BigBase = 10000;
- const int PerBitLen = 4;
- /* (1+x+x^2+x^3+…+x^(n-2)+x^(n-1))^2多项式乘法,系统最大项为x^(n-1)项,最大系数为n,而如果原来每一项前面都是BigBase,那么最大系数就变成
- BigBase*BigBase*n了,最大系数可以用2^64存储,若要保证n足够大,就要缩小BigBase
- */
- BigNumber *add(BigNumber *a,BigNumber *b,int offset)//可通过偏移来计算各种加法,O(N)
- {
- int nsize=a->size;
- char mark=-1;
- BigNumber *result=(BigNumber *)malloc(BigSize);
- if(offset==0)
- {
- if(a->size>b->size)
- {
- nsize=a->size;
- {
- BigNumber *newb=(BigNumber *)malloc(BigSize);
- newb->NumHead=(int *)malloc(4*nsize);
- newb->size=nsize;
- memset(newb->NumHead,0,4*(nsize-b->size));
- memcpy(newb->NumHead+nsize-b->size,b->NumHead,4*b->size);
- b=newb;
- }
- mark=1;
- }
- else if(a->size<b->size)
- {
- nsize=b->size;
- {
- BigNumber *newa=(BigNumber *)malloc(BigSize);
- newa->NumHead=(int *)malloc(4*nsize);
- newa->size=nsize;
- memset(newa->NumHead,0,4*(nsize-b->size));
- memcpy(newa->NumHead+nsize-a->size,a->NumHead,a->size*4);
- a=newa;
- }
- mark=0;
- }
- }
- else
- {
- if(a->size+offset>b->size)
- {
- nsize=a->size+offset;
- {
- BigNumber *newa=(BigNumber *)malloc(BigSize);
- BigNumber *newb=(BigNumber *)malloc(BigSize);
- newb->NumHead=(int *)malloc(4*nsize);
- newb->size=nsize;
- memset(newb->NumHead,0,4*(nsize-b->size));
- memcpy(newb->NumHead+nsize-b->size,b->NumHead,4*b->size);
- b=newb;
- newa->NumHead=(int *)malloc(4*nsize);
- newa->size=nsize;
- memset(newa->NumHead+a->size,0,4*offset);
- memcpy(newa->NumHead,a->NumHead,a->size*4);
- a=newa;
- }
- mark=2;
- }
- else if(a->size+offset<=b->size)
- {
- nsize=b->size;
- {
- BigNumber *newa=(BigNumber *)malloc(BigSize);
- newa->NumHead=(int *)malloc(4*nsize);
- newa->size=nsize;
- memset(newa->NumHead,0,4*nsize);
- memcpy(newa->NumHead+nsize-a->size-offset,a->NumHead,a->size*4);
- a=newa;
- }
- mark=0;
- }
- }
- result->NumHead=(int *)malloc(4*nsize);
- result->size=nsize;
- while(–nsize>=0)
- result->NumHead[nsize]=a->NumHead[nsize]+b->NumHead[nsize];
- if(mark==0)
- {
- free(a->NumHead);
- free(a);
- }
- else if(mark==1)
- {
- free(b->NumHead);
- free(b);
- }
- else if(mark==2)
- {
- free(a->NumHead);
- free(b->NumHead);
- free(a);
- free(b);
- }
- return result;
- }
- BigNumber *Merge(BigNumber * front,BigNumber * last,BigNumber * middle,int halfn)//整合函数 O(N)
- {
- int i;
- int carry=0,borrow=0;
- BigNumber *mid=add(add(front,middle,0),last,0);//2次内存申请与释放
- BigNumber *nonperfect=add(add(front,mid,halfn),last,halfn);//2
- BigNumber *result=(BigNumber *)malloc(BigSize);
- result->size=nonperfect->size+1;
- result->NumHead=(int *)malloc(4*nonperfect->size+4);//1
- result->NumHead[0]=0;
- memcpy(result->NumHead+1,nonperfect->NumHead,4*nonperfect->size);
- for(i=nonperfect->size;i>=0;–i)
- {
- int temp;
- result->NumHead[i]+=carry;
- result->NumHead[i]-=borrow;
- if((temp=result->NumHead[i])>=0)
- {
- carry=temp/BigBase;//进位
- result->NumHead[i]=temp%BigBase;//余位
- borrow=0;
- }
- else
- {
- carry=0;
- if((-result->NumHead[i])%BigBase==0)
- {
- borrow=(-result->NumHead[i])/BigBase;
- result->NumHead[i]=0;
- }
- else if(i!=0)//最高位无处借位
- {
- borrow=(-result->NumHead[i])/BigBase+1;
- result->NumHead[i]+=borrow*BigBase;
- }
- }
- }
- free(front->NumHead);
- free(middle->NumHead);
- free(last->NumHead);
- free(mid->NumHead);
- free(nonperfect->NumHead);
- free(front);
- free(middle);
- free(last);
- free(mid);
- free(nonperfect);
- if(result->NumHead[0]==0)
- {
- memcpy(result->NumHead,result->NumHead+1,(result->size-1)*4);
- result->size–;
- }
- return result;
- }
- BigNumber * sub(BigNumber *a,BigNumber *b)//差函数,不考虑借位与进位,O(N),2次内存释放与申请
- {
- int nsize=a->size;
- char mark=0;
- BigNumber *diff=(BigNumber *)malloc(BigSize);
- if(a->size>b->size)
- {
- BigNumber *c=(BigNumber *)malloc(BigSize);
- c->NumHead=(int *)malloc(4*a->size);
- c->size=a->size;
- memset(c->NumHead,0,4*(a->size-b->size));
- memcpy(c->NumHead+a->size-b->size,b->NumHead,4*b->size);
- b=c;
- nsize=a->size;
- mark=1;
- }
- else if(b->size>a->size)
- {
- BigNumber *c=(BigNumber *)malloc(BigSize);
- c->NumHead=(int *)malloc(4*b->size);
- c->size=b->size;
- memset(c->NumHead,0,4*(b->size-a->size));
- memcpy(c->NumHead+b->size-a->size,a->NumHead,4*a->size);
- a=c;
- nsize=b->size;
- mark=-1;
- }
- diff->NumHead=(int *)malloc(nsize*4);
- diff->size=nsize;
- while(–nsize>=0)
- diff->NumHead[nsize]=a->NumHead[nsize]-b->NumHead[nsize];
- if(mark==-1)
- {
- free(a->NumHead);
- free(a);
- }
- else if(mark==1)
- {
- free(b->NumHead);
- free(b);
- }
- return diff;
- }
- BigNumber *Mutiply(BigNumber *a,BigNumber *b)//
- {
- int nsize=max(a->size,b->size);
- if(a->size!=nsize)
- {
- BigNumber *c=(BigNumber *)malloc(BigSize);
- c->NumHead=(int *)malloc(4*nsize);
- c->size=nsize;
- memset(c->NumHead,0,4*(nsize-a->size));
- memcpy(c->NumHead+nsize-a->size,a->NumHead,4*a->size);
- free(a->NumHead);
- free(a);
- a=c;
- }
- if(b->size!=nsize)
- {
- BigNumber *c=(BigNumber *)malloc(BigSize);
- c->NumHead=(int *)malloc(4*nsize);
- c->size=nsize;
- memset(c->NumHead,0,4*nsize);
- memcpy(c->NumHead+nsize-b->size,b->NumHead,4*b->size);
- free(b->NumHead);
- free(b);
- b=c;
- }
- //对齐并变双
- if(nsize==1)
- {
- BigNumber *result=(BigNumber *)malloc(BigSize);
- long long temp=(long long)(a->NumHead[0])*(long long)(b->NumHead[0]);
- if(temp/BigBase==0)
- {
- result->NumHead=(int *)malloc(4);
- result->NumHead[0]=(int)temp;
- result->size=1;
- }
- else
- {
- result->NumHead=(int *)malloc(8);
- result->NumHead[1]=(int)(temp%BigBase);
- result->NumHead[0]=(int)(temp/BigBase);
- result->size=2;
- }
- free(a->NumHead);
- free(b->NumHead);
- free(a);
- free(b);
- return result;
- }
- else
- {
- int left=nsize/2;
- int right=nsize-left;
- BigNumber *a1=(BigNumber *)malloc(BigSize);
- BigNumber *a2=(BigNumber *)malloc(BigSize);
- BigNumber *b1=(BigNumber *)malloc(BigSize);
- BigNumber *b2=(BigNumber *)malloc(BigSize);
- a1->size=b1->size=left;
- a2->size=b2->size=right;
- a1->NumHead=(int *)malloc(4*left);
- b1->NumHead=(int *)malloc(4*left);
- a2->NumHead=(int *)malloc(4*right);
- b2->NumHead=(int *)malloc(4*right);
- memcpy(a1->NumHead,a->NumHead,4*left);
- memcpy(b1->NumHead,b->NumHead,4*left);
- memcpy(a2->NumHead,a->NumHead+left,4*right);
- memcpy(b2->NumHead,b->NumHead+left,4*right);
- free(a->NumHead);
- free(b->NumHead);
- free(a);
- free(b);
- nsize=nsize%2!=0?nsize+1:nsize;
- return Merge(Mutiply(a1,b1),Mutiply(a2,b2),Mutiply(sub(a2,a1),sub(b1,b2)),nsize/2);
- }
- }
- /////////////////////////////////初始化/////////////////////////////////////
- BigNumber *Int_BigInit(int tar)
- {
- int bitlen=(int)log10((long double)tar)/PerBitLen+1;
- BigNumber *Big=(BigNumber *)malloc(BigSize);
- Big->NumHead=(int *)malloc(4*bitlen);
- assert(Big!=NULL);
- Big->size=bitlen;
- //memset(Big->NumHead,0,4*(bitlen));
- while(–bitlen>=0)
- {
- Big->NumHead[bitlen]=tar%BigBase;
- tar/=BigBase;
- }
- return Big;
- }
- int BaseChange(char *str,int low,int up)
- {
- int i=up;
- int sum=0;
- for(;i>=low;–i)
- {
- if(str[i]==‘0’)continue;
- if(str[i]<‘0’||str[i]>‘9’)return -1;
- sum+=(str[i]-‘0’)*((int)pow((double)10,(double)up-i));
- }
- return sum;
- }
- BigNumber *Str_BigInit(char * str)
- {
- int strlenth,bitlen;
- int i=0,k=0;
- BigNumber *Big;
- assert(str!=NULL);
- while(*str++==‘0’);
- strlenth=strlen(–str);
- bitlen=strlenth/PerBitLen;
- /*strlenth–;
- bitlen–;*/
- if(strlenth%PerBitLen!=0)
- ++bitlen;
- Big=(BigNumber *)malloc(BigSize);
- Big->NumHead=(int *)malloc(4*(bitlen));
- //memset(Big->NumHead,0,4*(len+1));
- Big->size=bitlen;
- assert(Big->NumHead!=NULL);
- for(;bitlen>0;–bitlen,strlenth-=PerBitLen)
- {
- int max= strlenth-1;
- int min=strlenth-PerBitLen;
- min=min<0?0:min;
- Big->NumHead[bitlen-1]=BaseChange(str,min,max);
- }
- return Big;
- }
- /////////////////////////////////////////////////////////////////////////////
- void BigPrint(BigNumber * result,FILE *fp)
- {
- int i=0;
- assert(result!=NULL&&result->NumHead!=NULL);
- while(result->NumHead[i++]==0);
- fprintf(fp,“%d”,result->NumHead[i++]);
- for(;i<result->size;++i)
- {
- fprintf(fp,“%04d”,result->NumHead[i]);
- //fprintf(fp,”%01d”,result->NumHead[i]);
- }
- fprintf(fp,“/n”);
- }
- BigNumber * Factorial(int n)//测试阶乘
- {
- if(n==0||n==1)
- return Int_BigInit(n);
- else return Mutiply(Int_BigInit(n),Factorial(n-1));
- }
- int main()
- {
- //printf(“%d”,sizeof(long long));
- int i=0;
- clock_t start, finish;
- //fscanf(stdin,”%d”,&i);
- start=clock();
- BigPrint(Mutiply(Str_BigInit(“99912344444445384759347523452”),Str_BigInit(“11345623453452345235”)),stdout);
- finish=clock();
- printf(“用时 %lf 秒/n”,(double)(finish – start) / CLOCKS_PER_SEC);
- //BigPrint(BigMutiply(Str_BigInit(“479001600”),Int_BigInit(13)),stdout);
- return 0;
- }
- //程序频繁的申请与释放内存是个缺点,乘法复杂度为O(N 1.59),
大数乘法 分治法
原文作者:大整数乘法问题
原文地址: https://blog.csdn.net/fuchuangbob/article/details/3220156
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/fuchuangbob/article/details/3220156
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。