題意:讓你轉移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;
}