hdu 6237

(贪心)
题意:给定 n(n<105) 堆石子,每堆石子有 ai(ai<105) 个,每次操作可以将一个石子从一堆移动到另一堆,求最少的操作次数,使得存在一个数 x(x>1) ,使得每一堆石子均能被 x 整除。

思路:依题意可知,x必须为 Nn=1ai 的因子,于是我们先将 x 进行质因数分解,然后枚举每一个质因数。对于每一个质因数fac[i],求出每堆石子拿走 t[j] 才能被 fac[i] 整除,排序,然后从大到小贪心,把小的 t[j] 往大的上补,求出最少需要移动几个石子。

吐槽:题目难点在于如何贪心,如果同时考虑拿走多少个石子和需要补多少个石子,就会想复杂。所以要简化条件,只考虑一方面就可以求解。

代码:

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define LL long long

using namespace std;
const int maxn = 100010;
const LL inf = 1000000000000;

LL a[maxn], t[maxn];
LL fac[maxn], cnt;

void get_fac(LL x) {
    LL t = x; cnt = 0;
    for(LL i=2; i*i<=t; i++) if(t%i == 0) {
        while(t%i == 0) t /= i;
        fac[cnt++] = i;
    }
    if(t > 1) fac[cnt++] = t;
}

int main() {
    LL T, n;
    scanf("%lld",&T);
    while(T --) {
        scanf("%lld",&n);
        LL sum = 0;
        for(LL i=1; i<=n; i++) {
            scanf("%lld",&a[i]);
            sum += (LL)a[i];
        }
        sort(a+1, a+n+1);
        get_fac(sum);
        LL ans = inf;
        for(LL i=0; i<cnt; i++) {
            LL x = fac[i], res = 0, all = 0;
            for(LL j=1; j<=n; j++) {
                t[j] = a[j] % x;
                all += t[j];
            }
            sort(t+1, t+n+1);
            for(LL j=n; j>=1; j--) if(all > 0) {
                res += x-t[j];
                all -= x;
            }
            ans = min(ans, res);
            //printf("x:%lld res:%lld\n",x,res);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值