记录编号 143714 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2011]刷题计划 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.652 s
提交时间 2014-12-17 10:39:42 内存使用 1.46 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
#define sqr(x) ((x)*(x))
const int SIZEN=50010;
const double INF=1e10;
int N,M;
double L;
double A[SIZEN];
double dif[SIZEN];
LL calc_single_num(double a,double dt){//差为a,增量>=dt(增量是负的),最少需要切成几段
	double t=sqr(a)/(sqr(L)-dt);//k*(k+1)>=t的最小整数k
	if(t<=0) return 1;
	double x=(sqrt(4*t+1)-1)/2;
	return max(ceil(x),1.0);
}
LL calc_num(double dt,LL cnt[]){//增量>=dt,需要多少个题库中的题
	LL ans=0;
	for(int i=1;i<N;i++){
		cnt[i]=calc_single_num(dif[i],dt);
		ans+=cnt[i]-1;
	}
	return ans;
}
double calc_delta(double a,int k){//切成k+1段与k段相比的增量
	return sqr(L)-sqr(a)/(k*(k+1));
}
double calc_cost(double a,int k){//切成k段的耗费
	return sqr(a)/k-2*a*L+sqr(L)*k;
}
void answer(LL cnt[]){
	double ans=0;
	for(int i=1;i<N;i++) ans+=calc_cost(dif[i],cnt[i]);
	printf("%.3lf\n",ans);
}
void work(void){
	double mndif=INF,mxdif=-INF;
	for(int i=1;i<N;i++){
		mndif=min(mndif,fabs(dif[i]));
		mxdif=max(mxdif,dif[i]);
	}
	double l=calc_delta(mxdif,1),r=0;
	static LL cnt[SIZEN];
	if(l>=r){
		calc_num(0.0,cnt);
		answer(cnt);
		return;
	}
	int tot=0;
	while(++tot<=100){//二分最小增量
		double mid=(l+r)/2;
		LL now=calc_num(mid,cnt);
		if(now>M) r=mid;
		else l=mid;
	}
	calc_num(l,cnt);
	answer(cnt);
}
void read(void){
	scanf("%d%d",&N,&M);
	scanf("%lf",&L);
	for(int i=1;i<=N;i++) scanf("%lf",&A[i]);
	for(int i=1;i<N;i++) dif[i]=A[i+1]-A[i];
}
int main(){
	freopen("nt2011_seq.in","r",stdin);
	freopen("nt2011_seq.out","w",stdout);
	read();
	work();
	return 0;
}