洛谷1080-国王游戏(深入理解高精度乘 除)

题目链接:https://www.luogu.org/problem/show?pid=1080  国王游戏

这个题目的解析可以查看洛谷上的解析,我想写的是有关这个题目中的高精度问题。
 

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
const int maxm=1000000;
struct data
{
    int a,b;
} p[maxn];
int t[maxm];  ///第一位应该是所表示的大整数的位数也就是t[0],从第一位开始才是整数的每一位 依次从小到大排列,也就是105在数组中表示成501
int d[maxm];  ///d数组是中间做储存转换的作用,第一位仍然是整数位数
int ans[maxm];
int n;

bool Comp(data x,data y)
{
    return x.a*x.b<y.a*y.b;
}

void Times(int *X,int v,int *Y)  ///高精度乘法 是从最低位开始的,可以看做是模拟乘法运算
{
    int len=X[0];
    for (int i=1; i<=len+20; i++) Y[i]=0;
    for (int i=1; i<=len; i++) ///通过使x数组中的每一位与v相乘,%10,只取乘积的最后一位,/10加到下一位
    {
        Y[i]+=(X[i]*v);
        Y[i+1]+=(Y[i]/10);
        Y[i]%=10;
    }
    while (Y[len+1]>0)
    {
        len++;
        Y[len+1]+=(Y[len]/10);
        Y[len]%=10;
    }
    Y[0]=len;
}

void Div(int *X,int v,int *Y)  ///高精度除法
{
    int len=X[0];
    int rest=0;
    for (int i=len; i>=1; i--) ///这里注意:是从len开始的,也就是从整数的最大位开始的,可以看做模拟除法运算
    {
        rest=rest*10+X[i];
        Y[i]=rest/v;
        rest-=(v*Y[i]);  ///这里相当于是除法当中的取余数,和rest=rest*10+X[i]; 联系起来,就是一套完整的除法模拟
    }
    while (!Y[len]) len--;  ///这里有点绕,例如 运算出来Y数组数7000,可实际结果只是7,这一步是去除0操作
    if (!len) len=1;   ///倘若结果就是0000,上一步会把所有的0都去除,len会变成了0,这里就是避免这种情况,使len=1
    Y[0]=len;
}

void Get_max(int *X,int *Y)   ///大整数的比较函数
{
    if (Y[0]<X[0]) return;   ///先比较各自的位数,x[0],y[0]
    if (Y[0]==X[0])
        for (int i=Y[0]; i>=1; i--)
            if (Y[i]<X[i]) return;
            else if (Y[i]>X[i]) break;
    for (int i=0; i<=Y[0]; i++) X[i]=Y[i];  ///若Y大则把Y赋值给x
}

int main()
{
    scanf("%d",&n);
    for (int i=0; i<=n; i++) scanf("%d%d",&p[i].a,&p[i].b);
    sort(p+1,p+n+1,Comp);

    t[0]=1;
    t[1]=1;
    for (int i=1; i<=n; i++)
    {
        Times(t,p[i-1].a,d);
        for (int j=0; j<=d[0]; j++) t[j]=d[j];
        Div(t,p[i].b,d);
        Get_max(ans,d);
    }
    for (int i=ans[0]; i>=1; i--)
        printf("%d",ans[i]);  
    printf("\n");
    return 0;
}

这里的关键就是 Times()和Div()函数,一个是大整数的乘法,一个是大整数的除法运算。

大整数乘法运算Times():

           从最低那一位开始每一位乘以v,然后做/10和%10运算。

大整数除法运算Div():

           从最高那一位开始,每一项都试除以v,不够除则商0,然后*10+下一项。

这是总的思路,还需要注意的是乘法和除法始终是围绕x[],y[]展开的,它们的第0号元素都是指的这个数组代表的整数的位数。并且都是最低位在最前,依次列推直到最高位。

在大数乘法运算中,是从最低位开始一直到最高位,也就是从x[1]~x[len]

在大数除法运算中,是从最高位开始一直到最低位,也就是从x[len]~x[1]

具体的实现方法和细节在代码中展示了,请仔细阅读代码然后自己写出来。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值