2017ccpc哈尔滨区域赛H

时间:2024-04-03 20:37:44

n堆石子 每次只能拿一个石子从一堆移到另一堆  知道所有的堆的石子数目都能整除x(x>1) 问最小移动次数

枚举x的可能取值  即a[i]和的素因子即可  合因子的区间变化会比较大   然后求余 每次都把石子移到余数最大的那一堆,加起来的总和求最小值。

注意 开longlong

 #include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <queue>
#include <ctime>
#include <vector>
using namespace std;
const int maxn= 1e5+;
const int maxm= 1e6+;
const int inf = 0x3f3f3f3f;
typedef long long ll;
ll su[maxm];
int a[maxn],b[maxn];
int cnt,n;
void sushu(ll x)
{
cnt=;
for(int i=;i<=sqrt(x);i++)
{
if(x%i==)
su[cnt++]=i;
while(x%i==)
x/=i;
}
su[cnt++]=x;
}
int cmp(int a,int b)
{
return a>b;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
ll sum=;
for(int i=;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
sushu(sum);
ll maxx=;
for(int i=;i<cnt;i++)
{
ll sum=,cont=;
for(int j=;j<n;j++)
{
b[j]=a[j]%su[i];
sum+=b[j];
}
sort(b,b+n,cmp);
int k=;
while(sum!=&&k<n)
{
cont+=su[i]-b[k++];
sum-=su[i];
}
maxx=min(maxx,cont);
}
printf("%lld\n",maxx);
}
}