题意:
在给定的序列中,改变某些数的值,使他们形成递增的等差数列,求当个数值改变的量尽可能小(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 ;
}