【UOJ649】游泳

传送门

题意:

已知一个正整数数组 \(a\) 的长度是 \(m\) ,里面所有数字的和是 \(n\) 且任何两个相邻数字差的绝对值不超过 \(K\). 求 \(a\) 最大的可能方差乘上 \(m^2\) 的结果。如果 \(a\) 不存在输a出 \(-1\).

多测,\(n,k \le 10^8,m \le 100\)

首先特判 \(n<m\) 和 \(k=0\) 的情况,这是简单的。

考虑方差计算公式

\[s^2=\frac{1}{m}\sum_{i=1}^m (a_i-\overline{a})^2 \]

其中 \(\overline{a}\) 为 \(a\) 的平均数。其乘上 \(m^2\) 后化简为

\(ms^2=(m\sum a_i^2)-n^2\).

所以我们只需要最大化 \(\sum a_i^2\) 的值即可。

考虑由基本不等式得到 \((x+y)^2>x^2+y^2\). 所以差尽可能大,即 \(x+1,y-1\) 会比 \(x,y\) 优秀.

因此考虑让前面的数差为 \(k\),剩下的数字从后往前添加即可。(从前往后填会有一个位置差为 \(k+1\))

但注意到每段非空所以开始的时候每一段都 \(+1\) 然后 \(n \leftarrow n-m\).

#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define per(i,a,b) for(ll i=(a);i>=(b);i--)
#define op(x) ((x&1)?x+1:x-1)
#define odd(x) (x&1)
#define even(x) (!odd(x))
#define lc(x) (x<<1)
#define rc(x) (lc(x)|1)
#define lowbit(x) (x&-x)
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define next Cry_For_theMoon
#define il inline
#define pb(x) push_back(x)
#define is(x) insert(x)
#define sit set<int>::iterator
#define mapit map<int,int>::iterator
#define pi pair<int,int>
#define ppi pair<int,pi>
#define pp pair<pi,pi>
#define fr first
#define se second
#define vit vector<int>::iterator
#define mp(x,y) make_pair(x,y)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double db;
using namespace std;
const int MAXN=110;
ll T,n,m,k,c[MAXN],ans;
int main(){
	scanf("%lld",&T);
	while(T--){
		scanf("%lld%lld%lld",&n,&m,&k);
		if(n<m){printf("-1\n");continue;}
		if(!k){printf("%d\n",(n%m)?-1:0);continue;}
		ans=-n*n;
		rep(i,1,m)c[i]=1;
		n-=m;
		rep(i,1,m){
			//前i个+=k
			ll use=i*k;
			if(use>n || i==m){
				ll rest=n; 
				rep(j,1,i)c[j]+=rest/i;
				rest%=i;
				rep(j,1,rest){
					c[i-j+1]++;
				} 
				break;
			}else{
				rep(j,1,i)c[j]+=k;
				n-=use;
			}
		}
		rep(i,1,m)ans+=m*c[i]*c[i];
		cout<<ans<<endl;
	}

	return 0;
}
上一篇:【归并排序】AcWing 788. 逆序对的数量


下一篇:STL常用容器用法