CCF 1141.高精度除法(c/c++)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100;//实际可存位数=MAXN*4
struct bignum
{
	int num[MAXN],op;
	//op用来表示符号 num[0]用来保存数字位数,10000进制 节省空间和时间。
	
	/***********赋值号及初始化***********/
	bignum &  operator = (const char* c)//用字符数组赋值
	{
		memset(num,0,sizeof(num));
		int n,j=1,k=1;
		n=strlen(c);
		for (int i=1;i<=n;i++)
		{
			if (k==10000) j++,k=1;//10000进制,4个数字才算1位。
			if(c[n-i]=='-'&&i==n)op=-1;
			else num[j]+=k*(c[n-i]-'0');
			k*=10;
		}
		num[0]=j;
		return *this;
	}
	bignum &  operator = (int a)//用整型赋值
	{
		char s[MAXN*4];
		sprintf(s,"%d",a);
		return *this=s;
	}
	bignum(){memset(num,0,sizeof(num));num[0]=1;op=1;}  // 目的:声明bignum时无需显式初始化。
	bignum(int n){*this = n;} // 目的:支持“bignum a=1;”之类的代码。
	bignum(char *c){*this=c;}//用字符数组初始化
	void clear(){bignum a;*this=a;}//显性初始化
	
	/***********各种比较符号**********/
	bool  operator > (const bignum &b) const
	{
		if(op>b.op)return 1;
		if(op<b.op)return 0;
		if(op>0)//均为正数
		{
			if (num[0]!=b.num[0]) return num[0]>b.num[0];
			for (int i=num[0];i>=1;i--)
				if (num[i]!=b.num[i])
					return (num[i]>b.num[i]);
			return false;//相等时返回0
		}
		if (num[0]!=b.num[0]) return num[0]<b.num[0];
		for (int i=num[0];i>=1;i--)
			if (num[i]!=b.num[i])
				return (num[i]<b.num[i]);
		return false;//相等时返回0
	}
	bool  operator < (const bignum &b) const {return b>*this;}
	bool  operator <= (const bignum &b) const {return !(*this>b);}
	bool  operator >= (const bignum &b) const {return !(b>*this);}
	bool  operator != (const bignum &b) const {return (b>*this)||(*this>b);}
	bool  operator == (const bignum &b) const {return !(b>*this)&&!(*this>b);}
	
	/*************四则运算符*************/
	bignum  operator + (const bignum &b) const//加法同时处理减法
	{
		bignum c;
		if(op==b.op)
		{
			c.op=op;
			c.num[0] = max(num[0], b.num[0]);
			for (int i=1;i<=c.num[0];i++)
			{
				c.num[i]+=num[i]+b.num[i];
				if (c.num[i]>=10000)// 进位
				{
					c.num[i]-=10000;
					c.num[i+1]++;
				}
			}
			if (c.num[c.num[0]+1]>0) c.num[0]++;
			return c;
		}
		if(op==-1)
			return b+*this;
		bignum d=b;
		d.op=1;
		if(*this<d)
		{
			bignum e=*this;
			e.op=-e.op;
			d=b+e;
			d.op=-1;
			return d;
		}
		c.num[0] = num[0];
		for (int i=1;i<=c.num[0];i++)
		{
			c.num[i]+=num[i]-b.num[i];
			if (c.num[i]<0)// 退位
			{
				c.num[i]+=10000;
				c.num[i+1]--;
			}
		}
		while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;
		return c;
	}
	bignum  operator - (const bignum &b) const//减法就是被减数加减数的相反数
	{
		bignum c;
		c=b;
		c.op=-c.op;
		return *this+c;
		/*
		c.num[0] = num[0];
		for (int i=1;i<=c.num[0];i++)
		{
			c.num[i]+=num[i]-b.num[i];
			if (c.num[i]<0)// 退位
			{
				c.num[i]+=10000;
				c.num[i+1]--;
			}
		}
		while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;
		return c;
		*/
	}
	bignum &  operator += (const bignum &b) {return *this=*this+b;}
	bignum &  operator -= (const bignum &b) {return *this=*this-b;}
	bignum  operator * (const bignum &b) const
	{
		bignum c;
		c.num[0] = num[0]+b.num[0]+1;
		for (int i=1;i<=num[0];i++)
		{
			for (int j=1;j<=b.num[0];j++)
			{
				c.num[i+j-1]+=num[i]*b.num[j];
				c.num[i+j]+=c.num[i+j-1]/10000;        // 进位
				c.num[i+j-1]%=10000;
			}
		}
		while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;   // 99999999*0
		return c;
	}
	bignum &  operator *= (const bignum &b) {return *this=*this*b;}
	/*
	bignum  operator / (const bignum &b) const//朴素除法
	{
		bignum c, d;
		c.num[0] = num[0]+b.num[0]+1;
		d.num[0] = 0;
		for (int i=num[0];i>=1;i--)
		{
			// 以下三行的含义是:d=d*10000+num[i];
			memmove(d.num+2, d.num+1, sizeof(d.num)-sizeof(int)*2);
			d.num[0]++;
			d.num[1]=num[i];
			// 以下循环的含义是:c.num[i]=d/b; d%=b;
			while (d >= b)
			{
				d-=b;
				c.num[i]++;
			}
		}
		while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;   // 99999999/99999999
		return c;
	}
	*/
	bignum  operator / (const bignum& b) const//二分除法
	{
		bignum c, d;
		c.num[0] = num[0]+b.num[0]+1;
		d.num[0] = 0;
		for (int i=num[0];i>=1;i--)
		{
			// 以下三行的含义是:d=d*10000+num[i];
			memmove(d.num+2, d.num+1, sizeof(d.num)-sizeof(int)*2);
			d.num[0]++;
			d.num[1]=num[i];
			// 以下循环的含义是:c.num[i]=d/b; d%=b; 利用二分查找求c.num[i]的上界。
			// 注意,这里是二分优化后除法和朴素除法的区别!
			int left=0, right=9999, mid;
			while (left < right)
			{
				mid = (left+right)/2;
				if (b*bignum(mid) <= d) left=mid+1;
				else right=mid;
			}
			c.num[i]=right-1;
			d=d-b*bignum(right-1);
		}
		while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;
		return c;// 求余数就改成return d;
	}
	bignum operator % (const bignum & b)const
	{
		bignum c=*this/b;
		c*=b;
		return *this-c;
	}
	bignum &  operator /= (const bignum &b) {return *this=*this/b;}
	bignum &  operator %= (const bignum &b) {return *this=*this%b;}
	
	/*************特殊函数************/
	bignum abs()const
	{
		bignum a=*this;
		a.op=1;
		return a;
	}
	bignum pow(bignum x,int y)//快速乘
	{
		bignum ans=1;
		while(y)
		{
			if(y&1) ans=ans*x;
			x=x*x;
			y>>=1;	
		}
		return ans;
	}
};
ostream & operator << (ostream & out,const bignum &n)//流输出符
{
	if(n.op==-1)out<<'-';//先输符号
	out<<n.num[n.num[0]];
	for (int i=n.num[0]-1;i>=1;i--)
	{
		out.width(4);
		out.fill('0');
		out<<n.num[i];
	}
	return out;
}
istream & operator >> (istream & in,bignum &n)//流输入符
{
    char s[MAXN*4];
    in>>s;
    n=s;
    return in;
}
int main()
{
	bignum a,b;
	cin>>a>>b;
	cout<<a/b<<endl<<a%b;
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值