题意:让你转移n堆石子,每次最多转移1个,问最少的次数使得每堆石子的数量是x的倍数
解:
考虑,最后x一定也是sum的质因子。
对所有a[i]求余, 那么大的余数+上一部分就能变成mod 小的余数分到别人身上 自己变成0
只从将大的变成mod来分析不会出错,
因为从小的考虑的话,可能还是多个小的才凑出来,那么计算会不那么简洁
#include<bits/stdc++.h>
#define en '\n'
#define ll long long
const ll maxn=1e5+10;
using namespace std;
ll n,a[maxn];
ll sm=0;
const ll inf=0x3f3f3f3f3f3f3f3f;
#define all(x) x.begin(),x.end()
ll rd(){ll t;scanf("%lld",&t);return t;}
vector<ll>prime,vec;
signed main()
{
#ifdef swt
freopen("input2.txt","r",stdin);
#endif
int T;
cin>>T;
while(T--){
cin>>n;
sm=0;
for(ll i=1;i<=n;i++){
a[i]=rd();sm+=a[i];
}
#define pb push_back
prime.clear();
for(ll i=2;i*i<=sm;i++){
if(sm%i==0){
prime.pb(i);
while(sm%i==0)sm/=i;
}
}
if(sm>1){prime.pb(sm);}
sort(all(prime));
ll ans=inf;
for(ll i=0;i<prime.size();i++){
ll x=prime[i];vec.clear();
ll sum=0;
for(ll j=1;j<=n;j++){
if(a[j]%x==0)continue;
vec.pb(a[j]%x);
sum+=(a[j]%x);
}
sort(all(vec));
ll tem=0;
for(ll j=0;;++j)
{
tem+=vec[j];
sum-=prime[i];
if(sum<=0)break;
}
ans=min(ans,tem);
}
cout<<ans<<en;
}
return 0;
}