高精度压位模版

本文深入探讨了高精度算术的实现,包括加法、减法、乘法和除法等核心算法,并提供了详细的C++代码示例。通过具体题目如luogu1601、luogu2142、luogu1303等,文章展示了如何应用这些算法解决实际问题。
摘要由CSDN通过智能技术生成

注:昨天的高减重载小于运算符写错了,应该是倒序从高位到低位 ——2019.4.20


bool operator <(const num &p,const num &q){//比较大小 
	if(p.a[0]<q.a[0]) return true;
	if(p.a[0]>q.a[0]) return false;
	for(int i=p.a[0];i>=1;--i){//倒序 
		if(p.a[i]!=q.a[i]) return p.a[i]<q.a[i];
	}
	return false;
}

高精度加法

/***************************************
User:Mandy.H.Y
Language:c++
Problem:luogu1601 A+B Problem(压位)
Algorhithm:High Precision Addition
****************************************/

#include<bits/stdc++.h>

using namespace std;

const int power=4; //压位压四位 
const int base=1e4;
const int maxn=505;

struct num{
	int a[maxn];
	
	num(){memset(a,0,sizeof(a));}
	
	int &operator [](int x){return a[x];}//重载中括号 
	
	num(char *s){
		
		memset(a,0,sizeof(a));
		int len=strlen(s);
		
		a[0]=(len+power-1)/power;//计算位数
		
		for(int i=0,t=0,w=0;i<len;++i,w*=10){
			if(i%power==0) {w=1,++t;}//最好写成这种形式 
			a[t]+=(s[i]-'0')*w;
			
		}
	}
	
	void print(){
		printf("%d",a[a[0]]);
		for(int i=a[0]-1;i>0;--i) printf("%04d",a[i]);//printf("%0*d",power,a[i]); 
	}
}ans,p,q;

num operator +(num &p,num &q){//重载了中括号所以不用const 
	int cur=0,len=max(p[0],q[0]);
	for(int i=1;i<=len;++i){
		cur+=i<=p[0]?p[i]:0;
		cur+=i<=q[0]?q[i]:0;
		p[i]=cur%base;cur/=base;
	}
	if(cur) p[++len]=cur;
	p[0]=len;//注意更新长度 
	return p;
}

char p1[maxn],q1[maxn];
int lenp,lenq;

int main(){
	scanf("%s%s",p1,q1);
	
	lenp=strlen(p1);lenq=strlen(q1);
	reverse(p1,p1+lenp);reverse(q1,q1+lenq);
	
	p=num(p1);q=num(q1);
	
	ans=p+q;
	ans.print();
	return 0;
}

高精度减法

/**************************************
User:Mandy.H.Y
Language:c++
Pronblem:luogu2142 A-B Problem
Algorhithm:High Precision Subtraction 
**************************************/

#include<bits/stdc++.h>

using namespace std;

const int power=4;
const int base=1e4;
const int maxn=1e4+5;

struct num{
	int a[maxn];
	
	num(){memset(a,0,sizeof(a));}
	
	num(char *s,int len){
		memset(a,0,sizeof(a));
		
		a[0]=(len+power-1)/power;
		
		for(int t=0,w=1,i=len-1;i>=0;w=(w<<1)+(w<<3),--i){//倒序省去reverse
			if((len-1-i)%power==0){++t,w=1;}
			a[t]+=(s[i]^48)*w;
		}
	}
	
	void print(){
		printf("%d",a[a[0]]);
		for(int i=a[0]-1;i>0;--i) printf("%0*d",power,a[i]);
	}
}p,q,ans;

bool operator <(const num &p,const num &q){//比较大小 
	if(p.a[0]<q.a[0]) return true;
	if(p.a[0]>q.a[0]) return false;
	for(int i=p.a[0];i>=1;--i){//倒序 
		if(p.a[i]!=q.a[i]) return p.a[i]<q.a[i];
	}
	return false;
}

num operator -(num &p,num &q){
	int len=max(p.a[0],q.a[0]);
	for(int i=1;i<=len;++i){
		p.a[i]-=i<=q.a[0]?q.a[i]:0;
		if(p.a[i]<0) p.a[i]+=base,p.a[i+1]-=1;//借位 
	}
	while(p.a[0]>1&&p.a[p.a[0]]==0) --p.a[0];
	return p;
}

char p1[maxn],q1[maxn];
int lenp,lenq;

int main(){
	scanf("%s%s",p1,q1);
	lenp=strlen(p1);lenq=strlen(q1);
	p=num(p1,lenp),q=num(q1,lenq);
	if(q<p) ans=p-q;
	else putchar('-'),ans=q-p;
	ans.print();
	return 0;
}

高精度乘法

/*********************************************

User:Mandy.H.Y
Language:c++
Problem:luogu 1303 A*B Problem
Algorithm: High Precision Multiplication

**********************************************/

#include<bits/stdc++.h>

using namespace std;

const int power=4;
const int base=1e4;
const int maxn=2e3+5;

struct num{
	int a[maxn<<1];
	
	num(){memset(a,0,sizeof(a));}
	
	num(char *s,int len){
		memset(a,0,sizeof(a));
		
		a[0]=(len+power-1)/power;
		
		for(int t=0,w=1,i=len-1;i>=0;w=(w<<1)+(w<<3),--i){
			if((len-1-i)%power==0) w=1,++t;
			a[t]+=(s[i]^48)*w;//注意+= 
		}
	}
	
	void print(){
		printf("%d",a[a[0]]);
		for(int i=a[0]-1;i>0;--i) printf("%0*d",power,a[i]);
	}
}ans,p,q;

char p1[maxn],q1[maxn];
int lenp,lenq;

num operator *(const num &p,const num &q){
	num b;
	for(int i=1;i<=p.a[0];++i){
		int cur=0;
		for(int j=1;j<=q.a[0];++j)
			cur+=b.a[i+j-1]+p.a[i]*q.a[j],b.a[i+j-1]=cur%base,cur/=base;
			//cur+=b.a[i+j-1]+p.a[i]*q.a[j]累加 b.a[i+j-1]
		b.a[i+q.a[0]]=cur;
	}
	b.a[0]=q.a[0]+p.a[0];//得到大致位数 
	while(b.a[0]>1&&b.a[b.a[0]]==0) --b.a[0];//除去前导0 
	return b;
}

int main(){
	scanf("%s%s",p1,q1);
	lenp=strlen(p1);lenq=strlen(q1);
	p=num(p1,lenp);q=num(q1,lenq);
	ans=p*q;
	ans.print();
	return 0;
}

整合

/**************************
User:Mandy.H.Y
Language:c++
Problem:
Algorithm: High Precision
***************************/

#include<bits/stdc++.h>

using namespace std;

const int power=4;
const int base=1e4;
const int maxn=2e3+5;

struct num{
	int a[maxn<<1];
	
	num(){memset(a,0,sizeof(a));}
	int &operator [](int x){return a[x];}//重载中括号 
	num(char *s,int len){
		memset(a,0,sizeof(a));
		
		a[0]=(len+power-1)/power;
		
		for(int t=0,w=1,i=len-1;i>=0;w=(w<<1)+(w<<3),--i){
			if((len-1-i)%power==0) w=1,++t;
			a[t]+=(s[i]^48)*w;//注意+= 
		}
	}
	void add(int k) { if (k || a[0]) a[ ++a[0] ] = k; }     //在末尾添加一个数,除法的时候要用到  
    void re() { reverse(a+1, a+a[0]+1); } 
	void print(){
		printf("%d",a[a[0]]);
		for(int i=a[0]-1;i>0;--i) printf("%0*d",power,a[i]);
	}
}ans,p,q;

char p1[maxn],q1[maxn];
int lenp,lenq;


num operator +(num &p,num &q){//重载了中括号所以不用const 
	int cur=0,len=max(p[0],q[0]);
	for(int i=1;i<=len;++i){
		cur+=i<=p[0]?p[i]:0;
		cur+=i<=q[0]?q[i]:0;
		p[i]=cur%base;cur/=base;
	}
	if(cur) p[++len]=cur;
	p[0]=len;//注意更新长度 
	return p;
}

bool operator <(const num &p,const num &q){//比较大小 
	if(p.a[0]<q.a[0]) return true;
	if(p.a[0]>q.a[0]) return false;
	for(int i=p.a[0];i>=1;--i){//倒序 
		if(p.a[i]!=q.a[i]) return p.a[i]<q.a[i];
	}
	return false;
}

num operator -(num &p,num &q){
	int len=max(p.a[0],q.a[0]);
	for(int i=1;i<=len;++i){
		p.a[i]-=i<=q.a[0]?q.a[i]:0;
		if(p.a[i]<0) p.a[i]+=base,p.a[i+1]-=1;//借位 
	}
	while(p.a[0]>1&&p.a[p.a[0]]==0) --p.a[0];
	return p;
}

num operator / (num &p,num &q)               //注意const不要冲突 
{  
    num x, y;  
    for (int i = p.a[0];i >= 1;--i)                       //从最高位开始取数  
    {  
        y.add(p.a[i]);             //把数添到末尾(最低位),这时候是高位在前,低位在后  
        y.re();                    //把数反过来,变为统一的存储方式:低位在前,高位在后  
        while ( !(y < q) )         //大于等于除数的时候,如果小于的话,其实答案上的该位就是初始的“0”  
            y = y - q, ++x.a[i];   //看能减几个除数,减几次,答案上该位就加几次。  
        y.re();                    //将数反过来,为下一次添数做准备  
    }  
    x.a[0] = p.a[0];  
    while (x.a[0] > 0 && !x.a[x.a[0]]) --x.a[0];  
    return x;  
}  

num operator *(const num &p,const num &q){
	num b;
	for(int i=1;i<=p.a[0];++i){
		int cur=0;
		for(int j=1;j<=q.a[0];++j)
			cur+=b.a[i+j-1]+p.a[i]*q.a[j],b.a[i+j-1]=cur%base,cur/=base;
		b.a[i+q.a[0]]=cur;
	}
	b.a[0]=q.a[0]+p.a[0];//得到大致位数 
	while(b.a[0]>1&&b.a[b.a[0]]==0) --b.a[0];//除去前导0 
	return b;
}

int main(){
	
	/*
	scanf("%s%s",p1,q1);
	lenp=strlen(p1);lenq=strlen(q1);
	p=num(p1,lenp);q=num(q1,lenq);
	ans=p*q;
	ans.print();
	return 0;
	*/
	
	
	scanf("%s%s",p1,q1);
	
	lenp=strlen(p1);lenq=strlen(q1);
	
	p=num(p1,lenp);q=num(q1,lenq);
	
	ans=p+q;
	ans.print();
	return 0;
	
	
	
	/*
	
	scanf("%s%s",p1,q1);
	lenp=strlen(p1);lenq=strlen(q1);
	p=num(p1,lenp),q=num(q1,lenq);
	if(q<p) ans=p-q;
	else putchar('-'),ans=q-p;
	ans.print();
	return 0;

	*/
	
}

练习

luogu1255

luogu1255

/************************
User:Mandy.H.Y
Language:c++
Problem:luogu 1255 Staircase
Algorithm:High Precision Addition
************************/

#include<bits/stdc++.h>

using namespace std;

const int power=4;
const int base=1e4;
const int maxn=5005;

struct num{
	int a[maxn];
	num(){memset(a,0,sizeof(a));}
	int &operator [](int x){return a[x];}
	void print(){
		printf("%d",a[a[0]]);
		for(int i=a[0]-1;i>0;--i) printf("%04d",a[i]);
	}
}ans[5];

int n;

num operator +(num &p,num &q){
	int cur=0,len=max(p[0],q[0]);
	for(int i=1;i<=len;++i){
		cur+=i<=p[0]?p[i]:0;
		cur+=i<=q[0]?q[i]:0;
		p[i]=cur%base,cur/=base;
	}
	p[0]=len;//注意继承长度 
	if(cur) p[++p[0]]=cur;
	return p;
}

int main(){
	scanf("%d",&n);
	if(n==1) {puts("1");return 0;}
	if(n==2) {puts("2");return 0;}
	ans[1].a[0]=1,ans[2].a[0]=1;ans[1].a[1]=1,ans[2].a[1]=2;
	for(int i=3;i<=n;++i){
		ans[i%3]=ans[(i+1)%3]+ans[(i+2)%3];
	}
	ans[n%3].print();
	return 0;
}

luogu1604

luogu1604

/***************************
User:Mandy.H.Y
Language:c++
Problem:luogu1604 Planet
Algorithm:High Precision
***************************/

#include<bits/stdc++.h>

using namespace std;

const int power=1;
const int maxn=2e4+5;

int n,base;

struct num{
	int a[maxn];
	num(){memset(a,0,sizeof(a));}
	int &operator [](int x){return a[x];}
	num(char *s,int len){
		a[0]=len;
		for(int i=len-1;i>=0;--i){
			if(isdigit(s[i])) a[len-i]=s[i]^48;
			else a[len-i]=s[i]-'A'+10;
		}
	}
	void print(){
		for(int i=a[0];i>0;--i){
			if(a[i]<10) printf("%d",a[i]);
			else printf("%c",a[i]-10+'A');
		}
	}
}p,q,ans;

char p1[maxn],q1[maxn];
int lenp,lenq;

num operator +(num &p,num &q){
	int cur=0,len=max(p[0],q[0]);
	for(int i=1;i<=len;++i){
		cur+=i<=p[0]?p[i]:0;
		cur+=i<=q[0]?q[i]:0;
		p[i]=cur%base,cur/=base;
	}
	if(cur) p[++len]=cur;
	p[0]=len;
	return p;
}

int main(){
	scanf("%d",&base);
	scanf("%s%s",p1,q1);
	lenp=strlen(p1);lenq=strlen(q1);
	p=num(p1,lenp);q=num(q1,lenq);
	ans=p+q;
	ans.print();
	return 0;
}

部分引自:https://www.cnblogs.com/hnqw1214/p/6351321.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值