source:题目链接
题意:这是2016 ACM-ICPC China-Final的E题,题意是赌博游戏,给出n个队的赔率,问你最多能下注多少个队,才能使得不论你下注的这些队中哪一个队赢了你都可以赚,也就是说回报的金钱大于下注的总额。
思路:先用数学翻译一下此题,其实很简单就可以推出一个不等式:用P-i代表我下注的总额中第i个队占的金额占比,应有:P-i > A-i/(A-i+B-i)
要使得尽可能下注多的队,就将所有队的A-i/(A-i+B-i)排序,挨着取,直到总和>1
思路很简单,但是此题的坑在于如果单纯地用double的话会爆精度!所以有必要用高精度除法!
由于A-i/(A-i+B-i)一定是0.几的小数,所以直接用个二维数组存小数点后的数即可,排序,再用个sum数组记录累加和,直到进位产生时结束!
涉及到高精度除法,一定要注意的一个问题:四舍五入!!!(不加四舍五入过不了)
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define M 999
int num[105][M+5],stand[105],sum[M+5];
void cal_div(int x,int y,int quo[M+5]) //高精度除法
{
for(int i=0;i<=M;i++)
{
x*=10;
quo[i]=x/y;
x=x%y;
if(x==0) break;
}
if(quo[M]>=5) quo[M-1]++; //四舍五入!!!不加过不了!!
}
int cal_sum(int x[M+5],int y[M+5]) //高精度加法
{
int c=0;
for(int i=M-1;i>=0;i--)
{
x[i]=x[i]+y[i]+c;
c=x[i]/10;
x[i]=x[i]%10;
}
return c;
}
int cmp(const int x,const int y) //sort排序比较标准
{
int i=0;
while(num[x][i]==num[y][i] && i<M) i++;
return (num[x][i] < num[y][i]) ;
}
int main()
{
int t,T,n,xa,xb,ans;
double a,b;
scanf("%d",&T);
for(t=1;t<=T;t++)
{
scanf("%d",&n);
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
{
scanf("%lf:%lf",&a,&b);
xa=floor(a*1000+0.5);
xb=floor(b*1000+0.5);
cal_div(xa,xa+xb,num[i]);
}
for(int i=0;i<n;i++)
stand[i]=i;
sort(stand,stand+n,cmp);
int flag=0;
ans=0;
memset(sum,0,sizeof(sum));
while(flag==0 && ans<n)
{
flag=cal_sum(sum,num[stand[ans]]);
if(flag==0) ans++;
}
if(t==1) printf("Case #%d: %d",t,ans);
else printf("\nCase #%d: %d",t,ans);
}
return 0;
}