【CodeForces】【数学】【贪心】792E Colored Balls

CodeForces 792E Colored Balls

题目大意

NN个数中,每个数分成若干个数的和,要求必须由x,x1x,x-1构成。求出最少分出的集合个数。

分析

设我们最终从AiA_i分出的数的数量为kk,分出的数为x,x1x,x-1。则我们可以 通过打表 得到:kAik\le \sqrt{A_i}且有xAix\le \sqrt{A_i},且xx越大越好。

这告诉我们可以暴力枚举每块的大小。

我们将AA排序后来搞(因为xx最大不能够超过A1A_1)。

然后我们暴力枚举kk(即第一个数分开的个数,不超过A1\sqrt{A_1}),然后检验对于每个数是否成立,这时xx可以等于A1k+1\lfloor\frac{A_1}{k}\rfloor+1或者A1k\lfloor\frac{A_1}{k}\rfloor

当一个数AiA_i能被x,x1x,x-1分开时,令a=Aix,b=Aimod  xa = \lfloor\frac{A_i}{x}\rfloor,b=A_i\mod x,那么我们可以得到,当b=0b=0或者a+bx1a+b\ge x-1AiA_i可以被x,x1x,x-1分开。

就这样检验就可以了。

打表大法好啊!!!

参考代码

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 500;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;

int N;
int A[Maxn + 5];

void check(int siz) {
	ll sum = 0;
	for(int i = 1; i <= N; i++) {
		int p = A[i] / siz, q = A[i] % siz;
		if(q == 0 || p + q >= siz - 1)
			sum += p + (q != 0);
		else return;
	}
	printf("%lld\n", sum);
	exit(0);
}

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d", &N);
	for(int i = 1; i <= N; i++)
		scanf("%d", &A[i]);
	sort(A + 1, A + N + 1);
	int ans = INF;
	for(int i = 1; i * i <= A[1]; i++) {
		check(A[1] / i + 1);
		check(A[1] / i);
	}
	printf("%d\n", ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章