CF-394D Physical Education and Buns

题意:

在给定的序列中,改变某些数的值,使他们形成递增的等差数列,求当个数值改变的量尽可能小(k) 输出k,并且输出等差数列首项和公差。

分析:

若形成等差数列 即有:a[n]=a[0]+n*d;-->a[0]=a[n]-n*d;现在把每个值代进去,发现a[0]的值是不一样的。但是要形成等差数列,a[0]必定会一样。所以必须改变每个a[0]*.

从中我们可以选出一个最大的,和一个最小的。发现满足当个值该变量最少,正好是|Max-Min|所以刚好去(Max-Min)/2是最佳选择。故需要枚举公差d,选出最小的改变量k

而公差的范围不会很大,故枚举可以得到答案。另外,很明显d与k的函数关系具有U型关系,这就可以三分查找,得到k了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std ;
const int N=20005;
int a[1005];
int main()
{
	int i,j,n;
	int ans,A,d,Max,Min;
    while(cin>>n){
		for(i=0;i<n;i++){
			cin>>a[i];
		}
		sort(a,a+n);
		ans=N;
		for(i=0;i<N;i++){
			Max=-N;
			Min=N;
			for(j=0;j<n;j++){
				Max=max(Max,a[j]-i*j);
				Min=min(Min,a[j]-i*j);
			}
			if((Max-Min+1)/2<ans){
				ans=(Max-Min+1)/2;
				A=Min+ans;
				d=i;
			}		
		}
		cout<<ans<<"\n"<<A<<" "<<d<<endl;
    }
 	return 0 ;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值