题目链接:http://codeforces.com/contest/792/problem/E
假设含球较少的那些堆有 $mi$ 个球,较多的那些堆有$ma$个球,$ma=mi+1$,考虑对于最小的$a_i$枚举值 $mi$ ,表示我要将这堆求分成${left lfloor frac{a_i}{k} ight floor}$堆,每一堆$k$个,那么这种颜色就会有${{a_i ~~ mod ~~k}}$个球多出来,所以当且仅当 ${{left lfloor frac{a_i}{k} ight floorgeq (a_i ~~ mod ~~k)}}$ 才合法,然后对于剩下的$n-1$种颜色的判断一下这个$k$值是否合法,统计一下总数,因为这样的$k$对于最小的${a_i}$只有根号种取值,所以复杂度为${O(n* sqrt 1e9)}$
注意一下这种trick:答案爆$int$,枚举合法的$k$的时候要再判断一下${ai/k+1}$(样例),最后在算的时候是优先一堆放$ma$个的。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 100100 10 #define llg int 11 #define LL long long 12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 13 llg n,m,c[maxn],tail,a[maxn]; 14 LL ans=(LL)1e16; 15 16 inline int getint() 17 { 18 int w=0,q=0; char c=getchar(); 19 while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 20 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; 21 } 22 23 int main() 24 { 25 yyj("ball"); 26 cin>>n; 27 for (llg i=1;i<=n;i++) a[i]=getint(); 28 sort(a+1,a+n+1); 29 llg up=sqrt(a[1]+0.5); 30 for (llg i=1;i<=up;i++) if (a[1]/i>=a[1]%i) c[++tail]=i; 31 for (llg i=1;i<=up;i++) 32 { 33 llg k=a[1]/i; 34 if (a[1]/k>=a[1]%k) c[++tail]=k; 35 k--; if (!k) continue; 36 if (a[1]/k>=a[1]%k) c[++tail]=k; 37 } 38 for (llg i=1;i<=tail;i++) 39 { 40 llg k=c[i]; 41 bool pd=1; 42 for (llg j=1;j<=n;j++) if (a[j]/k<a[j]%k) pd=false; 43 if (pd) 44 { 45 LL sum=0; 46 for (llg j=1;j<=n;j++) sum+=a[j]/(k+1)+(a[j]%(k+1)!=0); 47 ans=min(ans,sum); 48 } 49 } 50 cout<<ans; 51 return 0; 52 }