题目描述

  给你 \(n,E,s_i,k_i,v_i'\),要求在

\[\sum_{i=1}^nk_i{(v_i-v_i')}^2s_i\leq E
\]

的前提下最小化

\[\sum_{i=1}^n\frac{s_i}{v_i}
\]

  \(n\leq 10000,0\leq E\leq {10}^8,0<s_i\leq {10}^5,0<k\leq 1,-100<v_i'<100\)

题解

  显然最优解会把体力浪完,所以约束的不等号可以换成等号。

  这样就变成了:在 \(G(V)=\sum_{i=1}^nk_i{(v_i-v_i')}^2s_i-E=0\) 的前提下最小化 \(F(V)=\sum_{i=1}^n\frac{s_i}{v_i}\)。

  运用拉格朗日乘法,有:

\[\begin{cases}
\sum_{i=1}^nk_i{(v_i-v_i')}^2s_i-E=0\\
\frac{s_i}{x_i^2}=2\lambda k_is_i(x_i-v_i)
\end{cases}
\]

  每个方程左边都是一个在第一象限的双曲线,右边是一条直线。

  所以一定有一个交点,且 \(\lambda>0\)。

  可以看出,当 \(\lambda\) 增大时,\(v_i\) 会减小,\(G\) 也会减小,所以 \(G\) 随 \(\lambda\) 递减。

  所以我们只需要二分 \(\lambda\),再二分 \(v_i\),判断 \(G\) 的负号即可。

  时间复杂度:\(的二分次数的二分次数O(n\times \lambda\text{的二分次数}\times v_i\text{的二分次数})\)

  二分上界我也不会算,就随便输了一个\({10}^{10}\)

  这题精度要求比较高,\(eps\)要设为\({10}^{-14}\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
int rd()
{
int s=0,c,b=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c=='-')
{
c=getchar();
b=1;
}
do
{
s=s*10+c-'0';
}
while((c=getchar())>='0'&&c<='9');
return b?-s:s;
}
void put(int x)
{
if(!x)
{
putchar('0');
return;
}
static int c[20];
int t=0;
while(x)
{
c[++t]=x%10;
x/=10;
}
while(t)
putchar(c[t--]+'0');
}
int upmin(int &a,int b)
{
if(b<a)
{
a=b;
return 1;
}
return 0;
}
int upmax(int &a,int b)
{
if(b>a)
{
a=b;
return 1;
}
return 0;
}
const double eps=1e-14;
int n;
double a[10010],k[10010],s[10010],v[10010];
double E;
void getv(double x)
{
for(int i=1;i<=n;i++)
{
double l=0,r=1e10;
while(r-l>eps)
{
double mid=(l+r)/2;
double s1=s[i]/mid/mid;
double s2=2*x*k[i]*s[i]*(mid-a[i]);
if(s1>s2)
l=mid;
else
r=mid;
}
v[i]=l;
}
}
double calc(double x)
{
getv(x);
double ans=0;
for(int i=1;i<=n;i++)
ans+=k[i]*s[i]*(v[i]-a[i])*(v[i]-a[i]);
return ans;
}
int main()
{
open("bzoj2876");
scanf("%d%lf",&n,&E);
for(int i=1;i<=n;i++)
scanf("%lf%lf%lf",&s[i],&k[i],&a[i]);
double l=0,r=1e10;
while(r-l>eps)
{
double mid=(l+r)/2;
if(calc(mid)>E)
l=mid;
else
r=mid;
}
getv(l);
double ans=0;
for(int i=1;i<=n;i++)
ans+=s[i]/v[i];
printf("%.10lf\n",ans);
return 0;
}

【BZOJ2876】【Noi2012】骑行川藏 拉格朗日乘法的更多相关文章

  1. [BZOJ2876][NOI2012]骑行川藏(拉格朗日乘数法)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2876 分析:就是要求约束条件下函数的极值,于是拉格朗日乘数列方程,发现化简后的关于vi ...

  2. bzoj 2876: [Noi2012]骑行川藏 拉格朗日数乘

    2876: [Noi2012]骑行川藏 Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1033  Solved: ...

  3. bzoj2876 [NOI2012]骑行川藏(拉格朗日乘数法)

    题目描述 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因此在每天的骑行 ...

  4. bzoj2876 [Noi2012]骑行川藏

    Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...

  5. BZOJ2876 [Noi2012]骑行川藏 【拉格朗日乘数法】

    题目链接 BZOJ 题解 拉格朗日乘数法 拉格朗日乘数法用以求多元函数在约束下的极值 我们设多元函数\(f(x_1,x_2,x_3,\dots,x_n)\) 以及限制\(g(x_1,x_2,x_3,\ ...

  6. 2876: [Noi2012]骑行川藏 - BZOJ

    Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...

  7. 【bzoj2876】 Noi2012—骑行川藏

    http://www.lydsy.com/JudgeOnline/problem.php?id=2876 (题目链接) 题意 在满足约束条件$${\sum_{i=1}^ns_ik_i(v_i-v_i' ...

  8. bzoj 2876: [Noi2012]骑行川藏【拉格朗日乘数法+二分】

    详见: http://blog.csdn.net/popoqqq/article/details/42366599 http://blog.csdn.net/whzzt/article/details ...

  9. 洛谷P2179 [NOI2012]骑行川藏(拉格朗日乘数法)

    题面 传送门 题解 看\(mashirosky\)大佬的题解吧--这里 //minamoto #include<bits/stdc++.h> #define R register #def ...

随机推荐

  1. spring----bean的使用

    这篇文章不介绍spring的相关概念,只记录一下springbean的创建方式和使用方式. 一.bean的创建和调用 1.创建演示需要用到的类:Student.Teacher.Person packa ...

  2. 从.Net到Java学习第七篇——SpringBoot Redis 缓存穿透

    从.Net到Java学习系列目录 场景描述:我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回.这个时候如果我们查询的某一个数 ...

  3. linux下sophos,clamav+clamtk杀毒软件

    以deepin为例 avast for linux sophos for linux comodo for linux 目前能够在官网找到. 先说clamav clamav 听说很活跃,clamav是 ...

  4. 26个ASP.NET常用性能优化方法

    数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源. ASP.NET中提供了连接池(Co ...

  5. SQLServer之修改表值函数

    修改表值函数注意事项 更改先前通过执行 CREATE FUNCTION 语句创建的现有 Transact-SQL 或 CLR 函数,但不更改权限,也不影响任何相关的函数.存储过程或触发器. 不能用 A ...

  6. SQLServr添加数据列

    数据列定义 表中数据行的数据插入和数据类型都是基于数据列的,学会添加数据列在开发过程中是必不可少的. 使用SSMS数据库管理工具添加数据列 在数据表中添加一列或者多列步骤相同 1.连接数据库,选择数据 ...

  7. C#基础知识之字符串比较方法:“==”操作符;RefernceEquals;String.Equals方法;String.Compare方法;String.CompareOrdinal方法。

    一.“==”操作符:String.Equals:ReferenceEquals 方法 1.在编程中实际上我们只需要这两种比较,c#中类型也就这两种 (1)值类型的比较:一般我们就是判断两个值类型实例各 ...

  8. Java线程锁,synchronized、wait、notify详解

    (原) JAVA多线程这一块有点绕,特别是对于锁,对锁机制理解不清的话,程序出现了问题也很难找到原因,在此记录一下线程的执行以及各种锁. 1.JAVA中,每个对象有且只有一把锁(lock),也叫监视器 ...

  9. 不安分的 Go 语言开始入侵 Web 前端领域了!( WebAssembly )

    参考:https://blog.csdn.net/csdnnews/article/details/84038848 从 Go 语言诞生以来,它就开始不断侵蚀 Java .C.C++ 语言的领地.今年 ...

  10. python实现数据结构单链表

    #python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" ...