Codeforces-792E Colored Balls(貪心/數學)
阿新 • • 發佈:2019-02-07
E. Colored Balls
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Examples
input
There are n boxes with colored balls on the table. Colors are numbered from 1 to n. i-th box contains ai balls, all of which have color i. You have to write a program that will divide all balls into sets such that:
- each ball belongs to exactly one of the sets,
- there are no empty sets,
- there is no set containing two (or more) balls of different colors (each set contains only balls of one color),
- there are no two sets such that the difference between their sizes is greater than 1.
Print the minimum possible number of sets.
InputThe first line contains one integer number n (1 ≤ n ≤ 500).
The second line contains n integer numbers a1, a2, ... , an (1 ≤ ai ≤ 109).
OutputPrint one integer number — the minimum possible number of sets.
3 4 7 8output
5input
2 2 7output
4
題解:設最少的球是有a[1]個,那麼所有set的容量一定不會超過a[1]+1(任意兩個set之間容量差不能超過1),只要列舉1~a[1]+1即可,只不過a[1]<=1e9,因此正常的暴力列舉是沒辦法過的。設s=sqrt(a[1]),那麼要列舉[1,s]是很容易的,但是要列舉[s,s^2]就需要轉化一下:
設k∈[s,s^2]為每個set的容量,那麼x=a[1]/k就表示第一個球需要用x個set裝,可以想到x∈[1,s],於是我們只要再列舉x就等於列舉完k。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MX = 505;
int n, a[MX];
bool Check1(int x, LL& cnt)
{
if (x <= 0) return false;
cnt = 0;
for (int i = 1; i <= n; i++) {
if (a[i] % x <= a[i] / x) { //每個set裝x個球,剩餘的球不能超過set的個數
cnt = cnt + (LL)ceil(a[i] * 1.0 / (x + 1));
}
else return false;
}
return true;
}
int main()
{
//freopen("in.txt", "r", stdin);
while (~scanf("%d", &n)) {
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a + 1, a + n + 1);
LL cnt = 0, ans = 1LL << 60;
int sq = (int)sqrt(a[1]) + 1;
//相當於列舉第一個球由sqrt(a[1])~a[1]個set裝
for (int i = 1; i <= sq; i++) {
int now = a[1] / i;
if (Check1(now, cnt)) ans = min(ans, cnt);
if (a[1] % i == 0) if (Check1(now - 1, cnt)) ans = min(ans, cnt);
if (ans != 1LL << 60) break;
}
//相當於列舉每個set裝1~sqrt(a[1])個球
for (int i = sq + 1; i >= 1; i--) {
if (Check1(i, cnt)) ans = min(ans, cnt);
if (ans != 1LL << 60) break;
}
printf("%I64d\n", ans);
}
return 0;
}