解题思路:
试商估算精确法
注意事项:注意要做减法的位置要对齐,冗余零要设置,大整数比较大小要弄明白位置
参考代码:
#include<stdio.h>
#include<string.h>
void shijinzhi(int *a,int k)//十进制函数,乘法中使用
{
if(a[k]>9)
{
a[k+1]+=a[k]/10;
a[k]=a[k]%10;
shijinzhi(a,k+1);
}
}
void cheng(int *a,int k,int len)//简易大整数乘法
{
for(int i=0;i<len;i++)
{
a[i]*=k;
}
for(int i=0;i<len;i++)
{
shijinzhi(a,i);
}
}
void diandao(int *a,int len)//颠倒数组
{
int temp;
for(int i=0,j=len;i<j;i++,j--)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
void jian(int *a,int k)//借位减法
{
int j=k;
if(a[j]<0)
{
a[j]=9;
j--;
a[j]--;
jian(a,j);
}
}
int find(int *a,int k)//寻找首位有效数字
{
int flag=k;
for(int i=0;i<=k;i++)
{
if(a[i]>0)
{
flag=i;
break;
}
}
return flag;
}
int compare(int *a,int *b,int j,int k)//大整数比较大小
{
for(int i=j-k,p=0;i<j;i++,p++)//找到需要比的第一位
{
if(a[i]>b[p])return 1;//因为是从高位比较到低位,所以可直接返回值
else if(a[i]<b[p])return -1;
}
return 0;//如果比到最后,那肯定是都一样大了
}
int main()
{
int a[305]={0},b[305]={0},c[305]={0},d[305]={0};//设置冗余零
char stra[300],strb[300];
scanf("%s%s",stra,strb);
int la=strlen(stra),lb=strlen(strb);
if(la>lb)
{
for(int i=0;i<la;i++)
{
a[i]=stra[i]-'0';
}
for(int i=0;i<lb;i++)
{
b[i]=strb[i]-'0';
}
}
else if(la<lb)//特殊情况,数组a小于数组b
{
printf("0\n");
printf("%s",stra);
return 0;
}
else
{
if(strcmp(stra,strb)>=0)
{
for(int i=0;i<la;i++)
{
a[i]=stra[i]-'0';
}
for(int i=0;i<lb;i++)
{
b[i]=strb[i]-'0';
}
}
else
{
printf("0\n");
printf("%s",stra);
return 0;
}
}
for(int i=lb-1,j=0;i<la;i++,j++)//除法初始位置是lb,但要注意数组中要减一
{
int h;
if(j==0)//首位特殊处理
{
h=(a[0]*10+a[1])/(b[0]*10+b[1]);
//这样的话试商比较准确,else分支同理
//因为设置了冗余零,不用担心程序崩溃,也不会影响试商
if(h==0)continue;
//特殊情况,最大的位置上都不够除,直接进入下一次循环
}
else
{
h=(a[j-1]*100+a[j]*10+a[j+1])/(b[0]*10+b[1]);
if(h==0)continue;//与上同理
}
c[lb]=0;//重置特殊位置冗余零
for(int k=0;k<lb;k++)//把数组b存到临时数组c中
{
c[k]=b[k];
}
diandao(c,lb-1);//颠倒数组c,准备做乘法
cheng(c,h,lb);
int len;
if(j==0)
{
len=lb-1;
//特殊情况处理,因为我的compare函数的比较逻辑中如果j==0时会越界崩溃,且此时需要比的位次就是从j开始
}
else
{
len=lb;
}
diandao(c,len);//继续颠倒数组,有冗余零不用担心
int flag=compare(a,c,i,len);
//从被除最高位前一位比较,因为前一位可能会有剩余的数
//此时冗余零不会影响比较,而且c数组乘完可能会多一位
while(flag<0)//如果不够除就把商减一再比较
{
h--;
c[lb]=0;
for(int k=0;k<lb;k++)
{
c[k]=b[k];
}
diandao(c,lb-1);
cheng(c,h,lb);
diandao(c,len);
flag=compare(a,c,i,len);
}
diandao(c,len);
diandao(c,lb);//统一减法位置
for(int o=1,p=i-lb+1;p<=i;p++,o++)
{
if(a[p]>=c[o])
{
a[p]-=c[o];
}
else
{
a[p]=a[p]+10-c[o];
a[p-1]--;
jian(a,p-1);
}
}
if(j>0)//如果c数组有进位就减,就算没有进位,此时冗余零也不影响
{
a[j-1]-=c[0];
}
d[j]=h;//记录到d数组
}
int key=find(d,la);//找到有效位置,去除前导零
for(int i=key;i<la-lb+1;i++)
{
printf("%d",d[i]);
}
printf("\n");
key=find(a,la);
for(int i=key;i<la;i++)
{
printf("%d",a[i]);
}
if(key==la)//特殊情况,余数为零
{
printf("0");
}
return 0;
}
0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复