您的位置:首页 > 其它

CCPC.2017 哈尔滨站-重现赛-H(暴力+贪心)

2017-11-11 17:42 267 查看


题意:给你一个序列,每次可以选择一个数a[i],将a[i]-1,并令其他任意一个数a[j]+1,这算作一个操作,问你至少需要多少操作使得该数组的所有数的最大公约数不是1。

题解:我们可以暴力该数组所有元素之和的所有质因数,对于每个质因数,暴力所有数让其达到该质因数的倍数,这里有一个简单的贪心思想,首先将所有数对当前质因数取模,然后从小到大排序,对于当前不为0的数,令其无脑加在末尾当前不是该质因数的数上即可。。。

题有个坑点:对于最大值上限不要无脑设成9e18,应该设成sum-max(a[i]),因为有可能所有元素之和是一个很大的质数,导致遍历不到时会影响答案(我wa了2小时。。。。。)

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
long long a[500005],b[500005]={1,1};
long long c[500005],d[500005],cnt,tmp[500005];
void init()
{
long long i,j;
for(i=2;i<500005;i++)
{
if(b[i])
continue;
c[++cnt]=i;
for(j=i*i;j<500005;j+=i)
b[j]=1;
}
}
int main(void)
{
init();
long long T,n,i,j;
long long sum;
scanf("%lld",&T);
while(T--)
{
long long ans,mx=0;
sum=0;long long num=0;
scanf("%lld",&n);
for(i=1;i<=n;i++)
scanf("%lld",&a[i]),sum+=a[i],mx=max(mx,a[i]);
for(i=1;i<=cnt && c[i]<=sum;i++)
if(sum%c[i]==0)
d[++num]=c[i];
ans=sum-mx;
for(i=1;i<=num;i++)
{
for(j=1;j<=n;j++)
tmp[j]=a[j]%d[i];
sort(tmp+1,tmp+n+1);
long long head=1,rear=n,t=0;
while(head<rear)
{
long long tt=min(d[i]-tmp[rear],tmp[head]);
tmp[rear]+=tt;tmp[head]-=tt;t+=tt;
if(tmp[rear]==d[i])
rear--;
if(tmp[head]==0)
head++;
}
ans=min(ans,t);
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: