题目链接: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]
具体的实现方法和细节在代码中展示了,请仔细阅读代码然后自己写出来。