标签:
/* 贪心:按照左右手乘积从小到大排序 证明: 设前i-1项 算出来为S i:a b i+1:c d 那么i+1处的金币为s*a/d i处为s/b 交换 i 和 i+1 i:c d i+1:a b 那么i+1处的金币为s*c/b i处为s/d 现在我们假设交换i 和 i+1 会得到更优的解 (交换前后的第i项显然小于i+1项 所以之比较第i+1) 则有 s*a/d > s*c/b --> a/d > c/b --> a*b>c*d 所以按照乘积从小到大 一定最优 然后就是 高精度0.0 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; ll n,c[10001],cc[10001],b[10001],d[10001],ans[10001]; struct node { int l; int r; }a[1001]; int cmp(const node &x,const node &y) { if(x.l*x.r<y.l*y.r)return 1; if(x.l*x.r>y.l*y.r)return 0; if(x.l*x.r==y.l*y.r) { if(x.r>y.r)return 1; else return 0; } } bool can()//是否需要更新最后答案 { if(d[0]>ans[0])return 1; if(d[0]<ans[0])return 0; int i; for(i=1;i<=d[0];i++) if(d[i]>ans[i])return 1; if(d[i]<ans[i])return 0; return 0; } void cheng(int x) { ll i,j,y=0; for(i=1;i<=c[0];i++) cc[i]=c[c[0]-i+1]; for(i=1;i<=c[0];i++) { cc[i]=cc[i]*x+y; y=cc[i]/10; cc[i]=cc[i]%10; } while(y>0)//高精乘单精时 注意处理最后一位 { cc[++c[0]]=y%10; y=y/10; } for(i=1;i<=c[0];i++) c[i]=cc[c[0]+1-i]; } void chu(int x) { memset(b,0,sizeof(b)); memset(d,0,sizeof(d)); int i,p=0,k=1; for(i=1;i<=c[0];i++) { b[i]=(p*10+c[i])/x; p=(c[i]+p*10)%x; } b[0]=c[0]; for(i=1;i<=b[0];i++) if(b[i]!=0) { k=i; break; } for(i=k;i<=b[0];i++) d[i-k+1]=b[i]; d[0]=b[0]-k+1; if(can()&&d[1]!=0) { memset(ans,0,sizeof(ans)); for(i=0;i<=d[0];i++) ans[i]=d[i]; } } int main() { cin>>n; ll i,j,o; n++; for(i=1;i<=n;i++) cin>>a[i].l>>a[i].r; sort(a+2,a+1+n,cmp);//排序 c[0]=1;c[1]=1; for(i=2;i<=n;i++) { cheng(a[i-1].l);//维护c 表示前面所有人的左手乘积 chu(a[i].r);//再÷此人的右手 记为ans } for(j=1;j<=ans[0];j++) cout<<ans[j]; return 0; }
标签:
原文地址:http://www.cnblogs.com/yanlifneg/p/5424062.html