传送门:www.lydsy.com:808/JudgeOnline/problem.php?id=2876
题解传送门:www.cppblog.com/prime56/archive/2012/08/13/187087.aspx
kAc神犇讲的东西,真心好用……
二分t,牛顿迭代解vi,与E比较大小,完了
明天就是noi2014了,祝我的学长以及faebdc&&Lavender怒拿Au
Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const double eps=1e-12;
int n;
double ans=1e100;
double E,s[maxn],k[maxn],vi[maxn],v[maxn],t;
double fv(int i,double v){
return 2.0*k[i]*(vi[i]-v)*v*v*t-1.0;
}
double fvd(int i,double v){
return -6.0*t*k[i]*v*v+4.0*t*k[i]*vi[i]*v;
}
double calc(int i){
int n=25;
double ans=10;
while(n--)ans-=fv(i,ans)/fvd(i,ans);
return ans;
}
bool ok(){
for(int i=1;i<=n;i++)
v[i]=calc(i);
double sum=0;
for(int i=1;i<=n;i++)sum+=s[i]*k[i]*(vi[i]-v[i])*(vi[i]-v[i]);
if(sum>E)
return true;
else
return false;
}
int main(){
scanf("%d%lf",&n,&E);
for(int i=1;i<=n;i++)scanf("%lf%lf%lf",&s[i],&k[i],&vi[i]);
//Min -> f(vi)=\sum_{i} si/vi
//g(vi)=\sum_{i} si*ki*(vi-vi')^2 -E = 0
//h(vi,t)= f(vi)+t*g(vi)
//h_vi'(vi,t)=-si*vi^-2 + 2tsi*ki*vi - 2tsi*ki*vi' = 0
// => -1 + 2tki*vi^3 - 2tki*vi'*vi^2 =0
// => 2ki(vi'-vi)vi^2 * t -1 =0
// t->upper vi->lower T->upper
//lower_bound t => calc vi
double l=-1,r=0;
for(int i=80;i;i--){
t=(l+r)/2.0;
if(ok())
r=t;
else
l=t;
}
double ans=0;
for(int i=1;i<=n;i++)ans+=s[i]/v[i];
cout<<fixed<<setprecision(12)<<ans<<endl;
return 0;
}