递归与分治——大整数乘法

递归与分治——大整数乘法

方法一:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
	int a[250],b[250],c[40000],la,lb;
	int result=0,carry=0,t=1;
	char a1[201],b1[201];
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c)); 
	gets(a1);
	gets(b1);
	la=strlen(a1);
	lb=strlen(b1);
	for(int i=0;i<=la-1;i++){
		a[la-i]=a1[i]-48;//倒序,并转化为数字 
	}
	for(int i=0;i<=lb-1;i++){
		b[lb-i]=b1[i]-48;//倒序,并转化为数字
	}
	for(int i=1;i<=lb;i++){
		carry=0;
		for(int j=1;j<=la;j++){
			t=j+i;
			result=a[j]*b[i]+carry+c[t-1];
			carry=result/10;
			c[t-1]=result%10;
		}
		while(carry){
			c[t++]=carry%10;
			carry=carry/10;
		}
	}
	while(c[t]==0){
		t--;
	}
	for(int i=t;i>=1;i--){
		cout<<c[i];
	}
	cout<<endl;
	return 0;
}

这个方法我觉得比较容易理解,就是逐位相乘后再相加,但要注意进位。

方法二:分治法

孙子兵法中有一句话“凡治众如治寡,分数是也。”这句话的大概意思是治理大军团就像治理小军团一样有效,是依靠合理的组织、结构、编制。而这变体现了分而治之的思想。
  在算法设计中,我们也引入分而治之的策略,称为分治算法,其本质就是将一个大规模的问题分解为若干个规模较小的相同子问题,分而治之。
  那什么样的问题可以用分治法解决呢?这要满足以下三个条件:

  1. 原问题可以分解为若干个规模较小的相同子问题。
  2. 子问题相互独立。
  3. 子问题的解可以合并为原问题的解。

以下是我在一本书中找到的对用分治法来解大整数乘法的一些理解
在这里插入图片描述
在这里插入图片描述
以下是书中的代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<ctime>
using namespace std;
#define M 1000
char sa[1000];
char sb[1000];
typedef struct _Node
{
	int s[M];
	int l;
	int c;
}Node,*pNode;
void cp(pNode src,pNode des,int st,int l)
{
	int i,j;
	for(i=st,j=0;i<st+l;i++,j++){
		des->s[j]=src->s[i];
	}
	des->l=l;
	des->c=st+src->c;
}
void add(pNode pa,pNode pb,pNode ans)
{
	int i,cc,k,palen,pblen,len;
	int ta,tb;
	pNode temp;
	if((pa->c<pb->c)){
		temp=pa;
		pa=pb;
		pb=temp;
	}
	ans->c=pb->c;
	cc=0;
	palen=pa->l+pa->c;
	pblen=pb->l+pb->c;
	if(palen>pblen){
		len=palen;
	}
	else{
		len=pblen;
	}
	k=pa->c-pb->c;
	for(i=0;i<len-ans->c;i++){
		if(i<k){
			ta=0;
		}
		else{
			ta=pa->s[i-k];
		}
		if(i<pb->l){
			tb=pb->s[i];
		}
		else{
			tb=0;
		}
		if(i>=pa->l+k){
			ta=0;
		}
		ans->s[i]=(ta+tb+cc)%10;
		cc=(ta+tb+cc)/10;
	}
	if(cc){
		ans->s[i++]=cc;
	}
	ans->l=i;
}
void mul(pNode pa,pNode pb,pNode ans)
{
	int i,cc,w;
	int ma=pa->l>>1,mb=pb->l>>1;
	Node ah,al,bh,bl;
	Node t1,t2,t3,t4,z;
	pNode temp;
	if(!ma||!mb){
		if(!ma){
			temp=pa;
			pa=pb;
			pb=temp;
		}
		ans->c=pa->c+pb->c;
		w=pb->s[0];
		cc=0;
		for(i=0;i<pa->l;i++){
			ans->s[i]=(w*pa->s[i]+cc)%10;
			cc=(w*pa->s[i]+cc)/10;
		}
		if(cc){
			ans->s[i++]=cc;
		}
		ans->l=i;
		return ;
	}
	cp(pa,&ah,ma,pa->l-ma);
	cp(pa,&al,0,ma);
	cp(pb,&bh,mb,pb->l-mb);
	cp(pb,&bl,0,mb);
	mul(&ah,&bh,&t1);
	mul(&ah,&bl,&t2);
	mul(&al,&bh,&t3);
	mul(&al,&bl,&t4);
	add(&t3,&t4,ans);
	add(&t2,ans,&z);
	add(&t1,&z,ans);
}
int main()
{
	Node ans,a,b;
	double duration=0;
	clock_t start,finish;
	cin>>sa;
	cin>>sb;
	start=clock();
	a.l=strlen(sa);
	b.l=strlen(sb);
	int z=0,i;
	for(i=a.l-1;i>=0;i--){
		a.s[z++]=sa[i]-'0';
	}
	a.c=0;
	z=0;
	for(i=b.l-1;i>=0;i--){
		b.s[z++]=sb[i]-'0';
	}
	b.c=0;
	mul(&a,&b,&ans);
	finish=clock();
	duration=(double)(finish-start)/CLOCKS_PER_SEC;
	for(i=ans.l-1;i>=0;i--){
		cout<<ans.s[i];
	}
	cout<<endl;
	cout<<duration<<endl;
	return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值