洛谷P2181 对角线(高精度)//高精度减法、高精度乘法、高精度除低精度

洛谷P2181 对角线

//原题链接:
https://www.luogu.com.cn/problem/P2181

//洛谷此题过去写的题解会在第4,7个点WA,
因为测试数据调整了,多了些极大的数据,必须用高精度才能过

此题涉及的重要知识点:
1.高精度的输入与输出
2.高精度的乘法、减法
3.高精度除低精度
(高精度除高精度和高精度的加法以后尝试)
#include
#include
using namespace std;

//读取高精度数据
void read(int a[])
{
string s; //先以字符串形式读入数据,方便之后的处理
cin>>s;
a[0]=int(s.size()); //用a数组的第0个位置存储 该数字的长度,十分便捷,这样就不需要在函数调用时传入两个参数了,且随身携带着,想用就用
for(int i=1;i<=a[0];i++)
{
a[a[0]+1-i]=int(s[i-1]-‘0’);
} //用a[i]存储数字的10^(i-1)位,所以要倒序存入,这样便于进行高精度运算

}

//高精度乘法
void multiple(int p[],int q[],int c[])
{
int a[105],b[105]; //在函数内创建动态数组,这样可以保护传入函数的数组,之前没这么做,结果做完运算后传入的数组也发生了变化,这不是我们所希望的
for(int i=0;i<=105;i++)
{
a[i]=p[i];
b[i]=q[i];
}
int x=0;
c[0]=1+a[0]+b[0];
for(int i=1;i<=a[0];i++)
{
for(int j=1;j<=b[0];j++)
{
c[i+j-1]=a[i]*b[j]+x+c[i+j-1]; //核心三行
x=c[i+j-1]/10; //若x>10,则产生进位
c[i+j-1]%=10; //每一位上数字不超过十
if(j==b[0]) //处理好边界很重要!
{
c[i+j]+=x;//可能的进位
x=0;//防止影响下一轮j循环运算!
}
}
}
while(c[c[0]]==0) c[0]–; //删除前导0,保证c数组位数记录的正确性
}

//高精度除低精度
void chu(int p[],int t,int b[])
{
int a[105]; //保护传入用来运算的p[]
for(int i=0;i<=105;i++)
{
a[i]=p[i];
}
int x=0;
b[0]=a[0];
for(int i=a[0];i>0;i–) //核心三行模拟竖式除法
{
a[i]+=x*10; //下移之前的余数
b[i]=a[i]/t; //取商
x=a[i]%t; //取余
}
while(b[b[0]]==0) b[0]–;//删除前导0
}

//高精度减法
void jian(int p[],int q[],int c[])
{
int a[105],b[105]; //复制 ->保护数据
for(int i=0;i<=105;i++)
{
a[i]=p[i];
b[i]=q[i];
}
c[0]=a[0];
for(int i=1;i<=a[0];i++)
{
if(b[i]>a[I]) //若不够,则借位
{
a[i+1] -=1;
a[i]+=10;
}
c[i]=a[i]-b[i];
}
while(c[c[0]]==0) c[0]–;//删除前导0
}

void output(int a[])//输出高精度数据
{
for(int i=1;i<=a[0];i++) cout<<a[a[0]+1-i];
cout<<endl;
}
int n[105],n1[105],n2[105],n3[105],temp1[105],temp2[105],temp3[105],sum[105];
int main()
{
read(n);
int yi[105]={1,1},er[105]={1,2},san[105]={2,3};

jian(n,yi,n1);
jian(n,er,n2);
jian(n,san,n3);

multiple(n,n1,temp1);
multiple(temp1,n2,temp2);
multiple(temp2,n3,temp3);     //其实可以优化,不用这么多temp

chu(temp3,24,sum);

output(sum);
return 0;

}

/long long n, sum;
cin>>n;
sum=n
(n-1)/2*(n-2)/3*(n-3)/4;
cout<<sum<<endl;
return 0;*/
//原来可以过的代码,现在测试多了大于long long 的测试数据

//小结
1.高精度的运算
a.最重要的就是要处理好运算过程中的进位
b.其次是操作的边界问题,如高精度乘法中的x,若不在每次内层循环中的if中置0,则会运算出错;还有处理运算后结果的前导0
c.其实高精度的运算最核心的也就三行代码:元操作与进位处理
d.重要的点:模拟、边界处理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值