题目链接
题意
给你n个盒子,每个盒子有ai个木块,现在可以将一些额外的木块放进n个盒子里面,求最小的额外木块数使得下面这个条件成立。
任意选择一个盒子,并从盒子取出所有木块,并且把木块分配到其他n-1个盒子中,使得这n-1个盒子的木块个数相等。
题解
方法一
设cnt为最小的额外木块数,sum为所有盒子的木块数
根据题意(即最终n-1个盒子的木块相等)可得(sum+cnt)%(n-1)==0。
而且还需要满足任意这个条件,我们模拟几个条件可以发现,当选择的盒子中木块数不是最大值时,剩下n-1个盒子的木块数最终都要大于等于最大值,而选择的盒子是最大值时,剩下n-1个盒子的木块数最终都要大于等于次大值(但是前面不是最大值已经满足了这个条件)。
翻译成数学公式就是,(sum+cnt)%(n-1)>=max。
总共需要满足的公式就是:
- (sum+cnt)%(n-1)==0
- (sum+cnt)%(n-1)>=max
因此根据上面这个公式我们可以直接算出来,最终答案就是
代码
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define debug puts("ac") #define INF 0x3f3f3f3f #define LINF 0x3f3f3f3f3f3f3f3f using namespace std; inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } const int N = 1e5+7; ll a[N]; int main(){ int T=read(); while(T--){ int n=read(); ll sum=0; rp(i,1,n) scl(a[i]),sum+=a[i]; ll MAX=*max_element(a+1,a+n+1); ll cnt=(sum+n-2)/(n-1); cout<<max(cnt,MAX)*(n-1)-sum<<endl; } return 0; }
方法二
因为最后剩下的n-1个数都相等,因此我们可以考虑二分枚举最终的n-1个数的值mid,注意左边界是MAX,方法一中已经解释了这个原因。
当mid*(n-1)>=sum时即符合条件,那么我们二分枚举最小的mid就行了。
代码
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <queue> #include <map> #include<numeric> using namespace std; typedef long long ll; const int INF = 1e9; int main() { int T;scanf("%d",&T); while(T--) { int n;scanf("%d",&n); vector<ll> v;v.clear(); for(int i=1;i<=n;i++){ ll x;scanf("%lld",&x); v.push_back(x); } ll sum=accumulate(v.begin(),v.end(),0*1ll); ll l = *max_element(v.begin(),v.end()),r = 2 * INF; ll ans = l; while(l <= r) { ll mid = (l + r) >> 1; if(1ll * mid * (n - 1) >= sum) { r = mid - 1; ans = mid; } else { l = mid + 1; } } printf("%lld\n",1ll * (n - 1) * ans - sum); } return 0; }