思想上确实是贪心但因为数据范围的问题我80%的时间都是在写高精(魔鬼)
本题的贪心策略的求解过程几乎是纯数学推导,但一旦把握了这个方向想推出来还是比较容易的,接下来只要耐心把排序和高精写好就可以了
那么来说一下推导过程:
首先是本题的无后效性:每个大臣得到的金币数并不会影响后续大臣得到的金币数,因为每位大臣得到的金币数都取决于自己右手的金币数。
确定这一点之后,不妨让我们请出队尾的两名大臣叶光迪和程驰(程驰为最后),他们左右手上的数字分别是x1,y1和x2,y2。
来分类讨论看看他们是如何走位排序来满足贪心国王的企图:
假设前面所有大臣左手数字总和为w
1.叶光迪在程驰前面时,他得到的金币数为 w/y1 ,而程驰得到的金币数为 w*x1/y2 。因此最多金币数gold1即为两式中较大的一项
2.程驰在叶光迪前面时,同理,最多金币数gold2为 w/y2 和w*x2/y1 中较大的一项
由题意得,既然叶光迪在程驰前面,那么说明gold1一定小于gold2,不然不会这么排序
本题最难理解的地方来了:若gold1<gold2,我们就可以得到 w*x1/y2<w*x2/y1 ,进而x1y1<x2y2
为什么呢? 进行一下数学推导:1.w*x2/y1>w/y1 w*x1/y2>w/y2
2.gold1和gold2不可能分别等于w/y1和w/y2(不符题意,自行证明)
3.当gold1=w/y1(w/y1>w*x1/y2) w/y2<w*x2/y1 所以w*x1/y2<w*x2/yi
这样,我们很愉快地得出了贪心策略:将左右手乘积小的大臣排在前面
感谢叶光迪和程驰大臣
1 #include<cstdio> 2 #include<iostream> 3 int n,l=1,a[100010],b[100010],c[100010]; 4 int g[1000010]; 5 void cheng(int x),chu(),sort(int l,int r); 6 int main() 7 { 8 scanf("%d %d %d",&n,&b[0],&c[0]); 9 for(int i=0;i<n;i++) 10 { 11 scanf("%d %d",&b[i],&c[i]); 12 a[i]=b[i]*c[i]; 13 } 14 g[1]=b[0]; 15 for(int i=1;i<n;i++) 16 cheng(i); chu(); 17 for(int i=l;i>=1;i--) printf("%d",g[i]); 18 return 0; 19 } 20 21 void chu(){ 22 for(int i=l;i>=1;i--) 23 { 24 g[i-1]+=((g[i]%c[n])*10); 25 g[i]/=c[n]; 26 } 27 while(g[l]==0) l--; 28 if(l==0) printf("1 "); 29 } 30 31 void cheng(int x){ 32 for(int i=1;i<=l;i++) 33 g[i]*=b[x]; 34 for(int i=1;i<=l;i++) 35 { 36 g[i+1]+=(g[i]/10); 37 g[i]%=10; 38 } 39 l++; 40 while(g[l]>9) 41 { 42 g[l+1]+=(g[l]/10); 43 g[l]%=10; 44 l++; 45 } 46 if(g[l]==0) l--; 47 } 48 49 void sort(int l,int r) 50 { 51 int le=l,ri=r,mid=a[(l+r)/2]; 52 while(le<=ri) 53 { 54 while(a[le]<mid) 55 le++; 56 while(a[ri]>mid) 57 ri--; 58 if(le<=ri) 59 { 60 int t=a[le]; 61 a[le]=a[ri]; 62 a[ri]=t; 63 64 t=b[le]; 65 b[le]=b[ri]; 66 b[ri]=t; 67 68 t=c[le]; 69 c[le]=a[ri]; 70 c[ri]=t; 71 le++; ri--; 72 } 73 } 74 if(l<ri) 75 sort(l,ri); 76 if(le<r) 77 sort(le,r); 78 }