poj2976(二分搜索,最大化平均值)
题目描述:
给了两个数组a,b,a[i]和b[i]是相对应的,不能改变位置,去掉其中的一些元素,然后计算最大的r=∑a[i]/∑b[i];
这道题乍一看是对a[i]/b[i]进行排序然后取前n-k个,但其实是不对的
题解:由题意得,我们要求的是r,所以对式子进行变形:设A=∑a[i],B=∑b[i],则A=r×B,A-r×B=0。所以为了求得最大的r,我们就要求使得A-rxB>0的最大的r,这样我们就可以另ci=ai-bi*r,然后对数组c进行排序即可
代码和学到的东西见下:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define ll long long 6 #define mem(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 ll a[1005],b[1005]; 9 double c[1005]; 10 int n,k; 11 bool cmp(ll a,ll b) 12 { 13 return a>b; 14 } 15 void trans(double x) 16 { 17 for(int i=1;i<=n;i++) 18 { 19 c[i]=100*a[i]-x*b[i];此处可以不乘100,在下面输出的时候再×100,可以省去很多计算 20 } 21 sort(c+1,c+1+n,cmp); 22 } 23 void ini() 24 { 25 mem(a,0); 26 mem(b,0); 27 mem(c,0); 28 } 29 int main() 30 { 31 while(scanf("%d%d",&n,&k)&&k+n>0){ 32 //ini(); 33 for(int i=1;i<=n;i++) scanf("%d",a+i); 34 for(int i=1;i<=n;i++) scanf("%d",b+i); 35 double l=0,r=1000; 36 for(int i=1;i<=50;i++) 37 { 38 double mid=(l+r)/2; 39 trans(mid); 40 double res=0; 41 for(int j=1;j<=n-k;j++) 42 { 43 res+=c[j]; 44 } 45 if(res>=0) l=mid; 46 else if (res<0) r=mid; 47 //printf("mid=%lf\n",mid); 48 } 49 printf("%d\n",(int)((l+r)/2+0.5));}//此处是四舍五入处理 50 //此处也可以输出l或者r,因为二分100次后小数位数而让输出整数已经可以忽略l和r的差异 51 return 0; 52 }
二分的题一定要注意精度!!
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· Cursor预测程序员行业倒计时:CTO应做好50%裁员计划
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争
· 用99元买的服务器搭一套CI/CD系统
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· Excel百万数据如何快速导入?