一、题目
二、解题思路
通过f(x)的取值可以看到,A[i]-A[i-1]的区间中f(x)值都一样,共有n+1个这样的区间,在每个区间里g可以看作每r个一组的等差数列,所以可以通过遍历1~n+1来做这道题。
for(long long i=1;i<=n;i++){
cin>>A[i];
B[i]=A[i]-A[i-1];//区间长度
}
B[n+1]=N-A[n];
使用等差数列求和的话,要保证r个g(x)相等的一组,所以每个区间对r整除和取模,剩下的几个数拿去和下一个数组的前面几个数凑一组(他们的g(x)相等)。然后将每个区间完整的g(x)组求和。:
long long Sum(long long first,long long count){//首项,项数
long long last =first+count-1;//末项
long long final;
//因为是绝对值求和,所以可能会有两段等差数列
if(last*first>=0)//同符号
return final=abs((first+last)*count/2*r);
else//不同符号,first是负数
return final=(abs(first)+1)*abs(first)/2*r+last*(last+1)/2*r;
}
for(long long i=1;i<=n+1;i++){
//每段区间的f(x)的值是i-1
Count=(B[i]+Sur)/r;//完整的g(x)组数
g=A[i-1]/r;//第一个g(x)的值
Error+=Sum(g-i+1,Count);
然后还要考虑一个问题,每个区间最后几个数本应该和当前f(x)做减法的,但是为了凑组,他们是和f(x)+1做了减法。
if(g-i+1>=0) Error+=Sur;//上一个组的后Sur个数的error值少加了1
else Error-=Sur;
Sur=(B[i]+Sur)%r;//更新Sur值
}
再加上最后一个区间的最后几个凑不够一组的g(x)的error值就好了。
g+=Count;//更新g值
Error+=abs(g-n)*Sur;//最后一个区间x值为n
cout<<Error;
三、完整代码
#include <bits/stdc++.h>
using namespace std;
const long long Maxn=1e5+5;
long long A[Maxn]={0};
long long B[Maxn]={0};
long long r;
long long Sum(long long first,long long count){
long long last =first+count-1;//末项
long long final;
if(last*first>=0)//同符号
return final=abs((first+last)*count/2*r);
else//不同符号,first是负数
return final=(abs(first)+1)*abs(first)/2*r+last*(last+1)/2*r;
}
int main(){
long long n,N;
long long Sur=0,Count,g;
long long Error=0;
cin>>n>>N;
r=N/(n+1);
for(long long i=1;i<=n;i++){
cin>>A[i];
B[i]=A[i]-A[i-1];//区间长度
}
B[n+1]=N-A[n];
for(long long i=1;i<=n+1;i++){
Count=(B[i]+Sur)/r;
g=A[i-1]/r;
Error+=Sum(g-i+1,Count);
if(g-i+1>=0) Error+=Sur;
else Error-=Sur;
Sur=(B[i]+Sur)%r;
}
g+=Count;
Error+=abs(g-n)*Sur;
cout<<Error;
return 0;
}