看到了一份能看懂的代码,先贴上来。再说我自己的想法。
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 500 +10;
const long long INF=0x7fffffffffffffff;
long long ans=INF;
long long a[MAXN];
int n;
void solve(long long x){
long long s=0;
if(x==0)
return;
for(int i=0;i<n;i++){
long long p=a[i]/x;
long long q=a[i]%x;
if(p==0)
return;
if(p>=q){
s+=(a[i]+x)/(x+1);
}else
return;
}
ans=min(ans,s);
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%I64d",a+i);
}
sort(a,a+n);
for(int i=1;i*i<=a[0];i++){
solve(a[0]/i);
solve(a[0]/i+1);
solve(i);
solve(a[0]/i-1);
}
printf("%I64d\n",ans);
}
其实就是暴力,因为每一份的个数肯定不能超过最小的数,所以针对最小的数枚举一下。不过在这个代码里面那个a[i]+x/(x+1)不太懂
我是用不定方程做的。
对于ax+by=n,x=x'-bt,y=y'+at.x',y'为一组特解。
对于p=a[I]/x,q=a[I]%x.
只要p>=q,就能把q分成q个1加到其他集合里面。(p-q)*x+q*(x+1)=a[i],总个数就是p+t,求出t的范围即可。
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 500 +10;
const long long INF=0x7fffffffffffffff;
long long ans=INF;
long long a[MAXN];
int n;
void solve(long long x){
long long s=0;
if(x==0)
return;
for(int i=0;i<n;i++){
long long p=a[i]/x;
long long q=a[i]%x;
if(p<q){
return;
}
long long X=(a[i]-q)/x;
long long Y=(p-q)/(x+1);
long long temp=min(X,Y);
s+=p-temp;
}
ans=min(ans,s);
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%I64d",a+i);
}
sort(a,a+n);
for(int i=1;i*i<=a[0];i++){
solve(a[0]/i);
solve(a[0]/i+1);
solve(i);
solve(a[0]/i-1);
}
printf("%I64d\n",ans);
}
然而居然被卡常乐。。
气哭