https://acm.ecnu.edu.cn/contest/92/problem/D/
D. 数蝌蚪
Time limit per test: 2.0 seconds
Memory limit: 256 megabytes
有 n 个装着小蝌蚪的水缸排成一排,你拥有一个无限蝌蚪的袋子,可以往一个水缸里放入一只蝌蚪,也可以取出一只蝌蚪,求最少的操作数,使得每个水缸的蝌蚪数量形成一个公差为 k 等差数列。
Input
第一行一个数 n,k(3⩽n⩽3×105,0⩽k⩽104)。
第二行 n 个数,表示每个水缸里的蝌蚪数目(0⩽ai⩽104)。
Output
输出最少操作次数。
Examples
input
4 2
1 2 3 4
output
4
input
4 2
0 1 2 3
output
6
Note
蝌蚪的个数不能是负的。
题目大意:最多进行多少次加减能使给定数列成为一个等差为k的数列(每次只能加或减一)
题解:代数分析+列式求解
具体地:先假设第一个数不变,然后用数组a[i]记录下后面的数与应得的数的差值,这时对第一个数进行操作 减 x ,那么后面的数则应进行操作abs(a[i]-x),则一共需要进行的操作次数是 abs(a[i]-x)从0到n-1的和,易知当x取数组a[i]的中位数时和最小,所以进行计算即可
[注意由改变后的数必须为非负数,所以需要对x的值进行限制]
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
long long orz[];
int main()
{
long long n,k;
scanf("%lld%lld",&n,&k);
long long a;
scanf("%lld",&a);
long long A=a;
orz[]=;
int q=,w=;
for(int i = ; i < n ; i++){
long long b;
scanf("%lld",&b);
orz[i]=-(b-k-A);
A=A+k;
}
long long sum=;
sort(orz,orz+n);
long long aa=;
long long asd=max(aa,(-n)*k);
long long ass=a-asd;
// cout << asd << endl;
if(orz[n/]>ass){
for(int i = ; i < n ;i++){
sum+=abs(orz[i]-ass);
} }
else{
for(int i = ; i < n ;i++){
sum+=abs(orz[i]-orz[n/]);
}
} cout << sum <<endl;
return ;
}