luoguP1080 国王游戏 (贪心+高精度)
题目链接:https://www.luogu.org/problemnew/show/P1080
参考:https://www.luogu.org/problemnew/solution/P1080
思路:这道题的考点是贪心和高精度。
贪心部分:
…(设这一段乘积为X1) | …(设这一段乘积为Y2) |
---|---|
L1 | R1 |
…(设这一段乘积为X2) | …(设这一段乘积为Y2) |
L2 | R2 |
由上面这张表格可以知道这样的情况时:
第一个人所得的金币数为X1/R1;
第二个人所得的金币数为X1×L1×X2/R2;
所以最小值为 max(X1/R1, X1×L1×X2/R2);
然后交换两个人的位置
…(这一段乘积为X1) | …(这一段乘积为Y2) |
---|---|
L2 | R2 |
…(这一段乘积为X2) | …(这一段乘积为Y2) |
L1 | R1 |
由上面这张表格可以知道交换后的情况时:
第一个人所得的金币数为X1×L2×X2/R1;
第二个人所得的金币数为X1/R2;
所以此时最小值为max(X1×L2×X2/R1, X1/R2);
综合上面两种情况:
如果变换之前的情况要优于变换之后的情况,那么
max(X1/R1, X1×L1×X2/R2) < max(X1×L2×X2/R1, X1/R2);
而X1/R1 < X1×L2×X2/R1 恒成立;
X1×L1×X2/R2 > X1/R2;
所以上述条件成立时
必须有X1×L1×X2/R2 < X1×L2×X2/R1 恒成立;所以化简可得 L1×R1 < L2×R2恒成立。
综上,很容易想到Li×Ri越大的应该排在越后面,所以对数据排个序就行。
另外就是高精度,数据最大可能达到10的4000次方,故需要使用高精度,这种高精度方法是参考的别人的,比较方便巧妙,不需要花费时间进行整数与字符串的转化。
代码如下:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 5 struct node{ 6 int a,b; 7 bool operator < (const node& other) const{ 8 return a*b<other.a*other.b; 9 } 10 }dat[1005]; 11 12 int n,in=1; 13 int hp[4005]; 14 15 void mul(int k){ 16 for(int i=1;i<=in;i++) 17 hp[i]*=dat[k].a; 18 for(int i=1;i<=in;i++){ 19 hp[i+1]+=hp[i]/10; 20 hp[i]%=10; 21 } 22 in++; 23 while(hp[in]>9){ 24 hp[in+1]=hp[in]/10; 25 hp[in]%=10; 26 in++; 27 } 28 if(hp[in]==0) 29 in--; 30 } 31 32 void div(){ 33 for(int i=in;i>=1;i--){ 34 hp[i-1]+=((hp[i]%dat[n].b)*10); 35 hp[i]/=dat[n].b; 36 } 37 while(hp[in]==0) 38 in--; 39 } 40 41 int main(){ 42 scanf("%d",&n); 43 for(int i=0;i<=n;i++) 44 scanf("%d%d",&dat[i].a,&dat[i].b); 45 sort(dat+1,dat+n+1); 46 hp[1]=dat[0].a; 47 for(int i=1;i<n;i++) 48 mul(i); 49 div(); 50 if(in==0) 51 printf("1"); //最终数组长度为0,由于每个人都会得到赏金,故每个人最多分到1赏金 52 else 53 for(int i=in;i>=1;i--) 54 printf("%d",hp[i]); 55 printf("\n"); 56 return 0; 57 }
朋友们,无论这个世界变得怎样,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。