• 【JZOJ4230】淬炼神体【数论,数学】【二分】


    题目大意:

    给出n,a[]n,a[]b[]b[],求在满足i=1nxi=msum^{n}_{i=1}x_i=mmax{i=1nai×xii=1nbi×xi}max{frac{sum^{n}_{i=1}a_i imes x_i}{sum^{n}_{i=1}b_i imes x_i}}


    思路:

    0/10/1分数规划裸体。
    推荐参考《算法竞赛进阶指南》P181P181
    随便取一个数LL,判断是否有一组x[]x[]满足i=1n(aiL×bi)Lsum^{n}_{i=1}(a_i-L imes b_i)geq L
    若有,那么变形得(i=1nai×xi)L×(i=1nbi×xi0)(sum^{n}_{i=1}a_i imes x_i)-L imes(sum^{n}_{i=1}b_i imes x_igeq 0)。则i=1nai×xii=1nbi×xiLfrac{sum^{n}_{i=1}a_i imes x_i}{sum^{n}_{i=1}b_i imes x_i}geq L
    所以答案就不小于LL,否则答案就小于LL
    那么就二分LL,知道精度小于10310^{-3}为止。


    代码:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int N=100010;
    int n,m;
    double l,r,mid;
    
    struct node
    {
    	int a,b;
    	double s;
    }a[N];
    
    bool cmp(node x,node y)
    {
    	return x.s>y.s;
    }
    
    bool check()  //判断最大的m个之和是否大于L
    {
    	double sum=0.0;
    	for (int i=1;i<=m;i++)
    		sum+=a[i].s;
    	return sum>=0;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&a[i].a);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&a[i].b);
    	l=0.0001;
    	r=20000.0;
    	while (r-l>=0.0001)  //二分L
    	{
    		mid=(l+r)/2.0;
    		for (int i=1;i<=n;i++)
    			a[i].s=(double)a[i].a/mid-(double)a[i].b;
    		sort(a+1,a+1+n,cmp);
    		if (check()) l=mid;
    			else r=mid;
    	}
    	printf("%0.3lf
    ",l);
    	return 0;
    }
    
  • 相关阅读:
    第八周总结和实验六
    第七周总结与实验五
    遍历目录中的所有文件和目录,并生成全路径
    python watchdog
    Offer_answer_with_SDP_rfc3264
    [转]UML八大误解
    leetcode周赛220
    Codeforces Round #690 (Div. 3)
    学习资料
    鱼眼图与六面图转换(python)
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998385.html
Copyright © 2020-2023  润新知