信息学奥赛一本通 1308 高精除

1308:【例1.5】高精除


时间限制: 1000 ms         内存限制: 65536 KB
提交数:25526    通过数: 12451

【题目描述】

高精除以高精,求它们的商和余数。

【输入】

输入两个低于300位的正整数。

【输出】

输出商和余数。

【输入样例】

1231312318457577687897987642324567864324567876543245671425346756786867867867
1231312318767141738178325678412414124141425346756786867867867

【输出样例】

999999999748590
179780909068307566598992807564736854549985603543237528310337
#include <bits/stdc++.h>
using namespace std;
char str1[305];//字符串储存 被除数 
char str2[305];//字符串储存 除数 
int temp[305];//补齐0后 临时数组 
int num1[305];//数组储存 被除数 
int num2[305];//数组储存 除数 
int ans[305]; //数组储存 商
void numcpy(int *num1,int *num2,int dest)//补齐函数
{
	//右移 左边空出dest个位置 补齐0
	for(int i=1;i<=num1[0];i++)//num1实际上代表除数
	{
		num2[i+dest-1]=num1[i];//num2实际上代表temp 
	 } 
	num2[0]=num1[0]+dest-1;//temp数组变更长度 
 } 
int compare (int *num1,int*num2)//比较函数
//引入 被除数 除数
{
	//一 比较数字长度 
	if (num1[0]<num2[0])//除数 大于 被除数 
	{
		return -1;
	}
	else if (num1[0]>num2[0])//被除数 大于 除数 
	{
		return 1; 
	}
	//二 数字长度相同 比较每一位
	for(int i=num1[0];i>0;i--)//高-低位 循环比较
	{
		if (num1[i]<num2[i])//除数 大于 被除数
		{
			return -1; 
		 } 
		else if (num1[i]>num2[i])//被除数 大于 除数
		{
			return 1;
		 }  
	 } 
	return 0;//大小相同 
 } 
int main()
{
	cin >> str1;//被除数 字符串输入 
	cin >> str2;//除数 字符串输入 
	//处理正负 
	bool flag1=false;//储存num1正负
	if (str1[0]=='-')//输入str1有负号 
	{
		flag1=true;//储存num1为负数
		strcpy(str1,&str1[1]);//覆盖负号 
	 }
	bool flag2=false;//储存num2正负
	if(str2[0]=='-')//输入str2有负号
	{
		flag2=true;//储存num2为负数 
		strcpy(str2,&str2[1]);//覆盖负号 
	  }
	//数据倒序
	int len=strlen(str1);//测量 被除数 长度
	num1[0]=len;//预留 num1第0位 储存 被除数长度
	for (int i=0;i<len;i++)//倒序 转数组 
	{
		num1[len-i]=str1[i]-'0';
	  }  
	len=strlen(str2);//测量 除数长度
	num2[0]=len;//同上 
 	for (int i=0;i<len;i++)//倒序 转数组
	{
		num2[len-i]=str2[i]-'0';
	  }  
	if (compare(num1,num2)==0)//被除数=除数
	{
		cout << 1 << endl << 0 << endl;
		//打印 商=1 余数=0  
		return 0; 
	  }
	else if (compare(num1,num2)==-1)//除数 大于 被除数
	{
		//商=0 余数为被除数
		cout << 0 << endl;//输出商
		if (flag1)//被除数=余数 为负数
		{
			cout << "-";//输出负号 
		 } 
		cout << str1 << endl;//输出 被除数字符串 已去负号  
	  }  	    
	else//被除数 大于 除数 
	{
		ans[0]=num1[0]-num2[0]+1;//商预计长度
		for (int i=ans[0];i>0;i--)//倒序处理答案
		{
			//利用临时数组temp补0对齐
			memset (temp,0,sizeof(temp));//初始化temp为0
			numcpy(num2,temp,i);//除数放入临时数组进行对齐 
			//逐步进行减运算 当 temp 小于 被除数 一直减
			while(compare(num1,temp)>=0)
			//被除数大于temp进行运算 
			{
				ans[i]++;//商加1
//				cout << "dfafadsf" << endl;
				for(int j=1;j<=num1[0];j++)//逐步进行减运算 
				//循环 被除数长度 次
				{
					if (num1[j]<temp[j])//判断是否需要进位
					{
						num1[j+1]--;
						num1[j]+=10;//进位 
					 } 
					num1[j]-=temp[j];//被除数-除数 
					
				  } 
				int tempk=num1[0];//定义临时 被除数位数
				while(num1[tempk]==0)//判断高位是否为0
				{
					tempk--;//临时位数变短 
				}
				num1[0]=tempk;//变更被除数位数  
			 } 
		 } 
	  } 
	//运算完成输出结果
	while(ans[0]>0&&ans[ans[0]]==0)//去除前导0
	//商不为0 有前导0 
	{
		ans[0]--;//位数变短 不输出前导0 
	  }  
	//打印商 余数
	if (!flag1 && flag2 || flag1 && !flag2)//被除数 除数有一个为负数->商为负数 
	{
		cout << "-";//输出负数 
	  }  
	for(int i=ans[0];i>0;i--)//倒序输出商
	{
		cout << ans[i];
	  }  
	cout << endl;//换行 
	if (num1[0]==0)//被除数无剩余=无余数
	{
		cout << 0 << endl;
		return 0; 
		  }	  
	else//有余数 
	{
		if(flag1)//被除数剩余=余数 为负数
		{
			cout << "-";//输出负号 
		 } 
		for (int i=num1[0];i>0;i--)//倒序输出余数
		{
			cout << num1[i];
		 } 
		 cout << endl;
		  }	  
	return 0;
 }

这段代码很长且不好理解 一定要搞清楚 很重要

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值