Educational Codeforces Round 18 E. Colored Balls

参考链接:http://www.cnblogs.com/barrier/p/6647594.html 

题目链接:http://codeforces.com/contest/792/problem/E

题目大意是将各种颜色的球分组,要求每组只能有一种颜色并且任一两组球个数之差不能大于一。

枚举+贪心

刚开始看觉得需要判断x-1,x与x,x+1两种情况,但是实际上x-1,x可以包括在x,x+1的情况中

引用参考链接中的:

设每个盒子中可以存放xx+1个球,则任意颜色的球的个数都可以表示为ux+v(x+1).

故可任选一种颜色的球a,枚举p,令k=a/pr=a%p,即a=kp+r.

根据r的值,可分为两种情况:

  • r0时,x仅有两种可能,x=kx=p.
  • r=0时,x有四种可能,x=kx=px=k1x=p1.

将上面得到的x带入各个颜色检验,由于要求最少盒子,故优先以x+1x+1为单位将球分组:ai=k(x+1)+r.

如果ai%(x+1)!=0的话,则ai%x<=ai/x

p实际上只用枚举到sqrt(ai)即可,否则可能超时

注意结果可能为多个10e9相加,因此要long long.

代码:

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<vector>
 8 #include<string>
 9 #include<map>
10 using namespace std;
11 
12 const int maxn = 505;
13 const long long inf = 0x3f3f3f3f3f3f3f3f;
14 int n;
15 int a[maxn];
16 
17 long long check(int p)
18 {
19     long long res = 0;
20     for (int i = 0; i < n; i++)
21     {
22         if (a[i] % (p + 1) != 0 && a[i] % (p) > a[i] / p) return inf;
23         res += a[i] / (p + 1) + (a[i] % (p + 1) == 0 ? 0 : 1);
24     }
25     return res;
26 }
27 
28 int main()
29 {
30     cin >> n;
31     for (int i = 0; i < n; i++)
32     {
33         scanf("%d", &a[i]);
34     }
35     long long res = inf, k = 0, b = a[0];
36     for (int i = 0; i < n; i++)
37         if (b > a[i]) b = a[i];
38     for (k = 1; k*k <= b; k++)
39     {
40         int p = b / k;
41         res = min(res, check(k));
42         res = min(res, check(p));
43         int r = b%k;
44         if (r == 0)
45         {
46             res = min(res, check(k - 1));
47             res = min(res, check(p - 1));
48         }
49     }
50     cout << res << endl;
51     return 0;
52 }
原文地址:https://www.cnblogs.com/bolderic/p/6658574.html