题解:
手模几组样例,可以发现应该是往打勾函数方向靠。
同时,如果限制
a
a
a 只能为整数,那么容易想到设
f
i
,
x
f_{i,x}
fi,x 表示前
i
i
i 个数,最后一个数是
x
x
x 的最小答案。且
f
[
i
]
[
x
]
=
m
i
n
j
≥
b
i
−
1
x
f
[
i
−
1
]
[
j
]
+
x
f[i][x]=min_{j\geq \frac{b_{i-1}}{x}}f[i-1][j]+x
f[i][x]=minj≥xbi−1f[i−1][j]+x
但实数域无法穷尽,这时我们发现任意一个
f
f
f 可以表示成
a
x
+
b
x
+
c
ax+\frac{b}{x}+c
ax+xb+c 的形式,因为
b
i
x
\frac{b_i}{x}
xbi 代入不会改变形式,而当取常数时又变成
a
x
+
c
ax+c
ax+c 同样满足。同时可以发现任意一个
f
f
f 都是下凹函数,且只有一个极点,具体证明用递推。
#include<bits/stdc++.h>
#define N 2005
#define eps 0.00000001
#define inf 1000000000.0
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
double b[N];
double t[N][5],s[N][5];
int st,tt,n;
inline void clear(int x){
for(int j=0;j<5;++j)s[x][j]=0;
}
int main(){
n=read();
for(int i=1;i<n;++i)b[i]=read();
++st;
s[st][0]=1,s[st][1]=b[1];
s[st][3]=eps,s[st][4]=inf;
for(int g=2;g<n;++g){
tt=0;
while(st){
double k=sqrt(s[st][1]/s[st][0]);
if(k<s[st][3]||k>s[st][4]){
++tt;
t[tt][3]=(s[st][4]==inf)?eps:b[g]/s[st][4];
t[tt][4]=(s[st][3]==eps)?inf:b[g]/s[st][3];
t[tt][0]=(s[st][1]/b[g]+1);
t[tt][1]=(s[st][0]*b[g]);
t[tt][2]=s[st][2];
}else{
++tt;
t[tt][3]=(s[st][4]==inf)?eps:b[g]/s[st][4];
t[tt][4]=(k==eps)?inf:b[g]/k;
t[tt][0]=(s[st][1]/b[g]+1);
t[tt][1]=(s[st][0]*b[g]);
t[tt][2]=s[st][2];
++tt;
t[tt][3]=b[g]/k;
t[tt][4]=inf;
double minn=2*sqrt(s[st][1]*s[st][0])+s[st][2];
t[tt][1]=0;
t[tt][2]=minn;
t[tt][0]=1;
st=1;
}
--st;
}
for(int i=1;i<=tt;++i){
clear(i);
for(int j=0;j<5;++j)s[i][j]=t[i][j];
}
st=tt;tt=0;
}
double ans;
for(int i=1;i<=st;++i){
double k=sqrt(s[i][1]/s[i][0]);
if(k>=s[i][3]&&k<=s[i][4]){
ans=2*sqrt(s[i][1]*s[i][0])+s[i][2];
break;
}
}
printf("%.6lf\n",ans);
return 0;
}