CodeForces 792E Colored Balls
题目大意
将个数中,每个数分成若干个数的和,要求必须由构成。求出最少分出的集合个数。
分析
设我们最终从分出的数的数量为,分出的数为。则我们可以 通过打表 得到:且有,且越大越好。
这告诉我们可以暴力枚举每块的大小。
我们将排序后来搞(因为最大不能够超过)。
然后我们暴力枚举(即第一个数分开的个数,不超过),然后检验对于每个数是否成立,这时可以等于或者。
当一个数能被分开时,令,那么我们可以得到,当或者时可以被分开。
就这样检验就可以了。
打表大法好啊!!!
参考代码
#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;
}