记录编号 242541 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2011]刷题计划 最终得分 100
用户昵称 Gravatarmikumikumi 是否通过 通过
代码语言 C++ 运行时间 0.644 s
提交时间 2016-03-27 17:31:39 内存使用 1.27 MiB
显示代码纯文本
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
const int SIZEN=50010,INF=0x7fffffff/2;
const double zero=1e-13;
int N,M;
double L;
double a[SIZEN];
double d[SIZEN];
double sqr(double x)
{
	return x*x;
}
void read()
{
	scanf("%d%d",&N,&M);
	scanf("%lf",&L);
	for(int i=1;i<=N;i++) scanf("%lf",&a[i]),d[i]=a[i]-a[i-1];
}
int piece[SIZEN];
double Calc_cost(double a,double y)//把a分成y个段的代价
{
	double re=a*a/y-2.0*a*L+y*L*L;
	return re;
}
int cut(double d,double x)//初中知识...
{
	double t=sqr(d)/(sqr(L)-x);
	if(t<=0) return 1;
	//cout<<t<<endl;
	double ans=(sqrt(4*t+1)-1)/2.0;
	return max(ceil(ans),1.0);
}
int Calc_sum(double x)//把所有的区间的增量变成x的切割次数
{
	int ans=0;
	for(int i=2;i<=N;i++)
	{
		int tem=cut(d[i],x);
		piece[i]=tem;
		ans+=tem-1;
	}
	return ans;
}
double get()//
{
	double ans=0;
	for(int i=2;i<=N;i++) ans+=Calc_cost(d[i],piece[i]);
	return ans;
}
void work()
{
	double ma=-INF;
	for(int i=2;i<=N;i++)
		ma=max(d[i],ma);
	//cout<<ma<<endl;
	double l=sqr(L)-sqr(ma)*(0.5),r=0.0;
	double ans=0;
	if(l>=r)//不用加点已经是最优的
	{
		for(int i=2;i<=N;i++) piece[i]=1;
		ans=get();
		printf("%.3lf\n",ans);
		return;
	}
	int tot=0;
	while(++tot<=100)
	{
		double mid=(r+l)/2.0;
		int tem=Calc_sum(mid);
		if(tem>M) r=mid;
		else l=mid;
	}
	Calc_sum(l);
	//for(int i=1;i<=N;i++) cout<<piece[i]<<" ";
	//cout<<endl;
	ans=get();
	printf("%.3lf\n",ans);
}
int main()
{
	freopen("nt2011_seq.in","r",stdin);
	freopen("nt2011_seq.out","w",stdout);
	read();
	work();
	return 0;
}