DTOJ#5315. 「CTS2021 / CTSC2021」数组

题目链接

题解:
手模几组样例,可以发现应该是往打勾函数方向靠。
同时,如果限制 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]=minjxbi1f[i1][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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值