HDU - 6237 A Simple Stone Game 分解质因数 + 贪心

1.题意:给你n堆石头,每堆有a[i]个石头,每次可以从一堆移动一颗石头到另一堆,问最小的移动次数使存在x让所有a[i]%x ==0 成立。即最后的每堆石头都有一个共同的公因数(x>1)

2.分析:

(1)因为石头的总数在移动中是不变的,所以如果最后 a[0]%x==0 && a[1]%x==0 && a[2]%x==0 && ......&&a[n]%x==0

则有: a[0]%x + a[1]%x + a[x]%x + ....... + a[n]%x == 0

由取余运算知:(a[0] + a[1] + a[2] + ..... + a[n])%x==0

也就是说:这个因数x一定是 石子和 sum 的一个因数。

(2)由以上知:我们可以求出sum所有的质因数(非质因数也一定包含质因数,只需求质因数即可),枚举所有质因数下的最小移动次数即可。

(3)怎么判断移动次数呢?在已知x情况下,每堆石头距离成为x的倍数,最少差b[i] =  a[i]%x个石头,这就是这堆石头需要补的石子数目。把所有堆石头需要补的数目求出来(不一定是补,还有可能是拿走),如果b[i]很小,我们拿到余数为0是这堆移动最少的。如果b[i]很大,我们补到x是最少的。那我们先补大的还是先拿小的呢?如果我们拿走了小的,那么小的放在哪呢?所以我们应该先补大的,补的数目就来自于前方小的,哪一堆?不用关心

(4)我们需要移动改变的总石子数ans = (b[0] + b[1] + b[2] + .... + b[n]),可以证明ans%x==0

如果我们补好了一个大的,那么这需要修改的石子总数就减少了x,移动次数 =x -  b[i]

如果ans到了0,那么就说明所有石子都移动好了,当前操作次数就是总次数

3.代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define INF 1e18//因为LL,所以最大要设置LL最大
const int maxn = 100000 + 7;
typedef long long LL;
LL stone[maxn],fac[maxn],len;
LL num[maxn];
LL sum;
int n;
void Reslove(LL ans){//分解质因数
   for(LL i = 2;i*i<=ans;i++){
       if(ans&&ans%i==0){
           fac[len++] = i;//保存
           while(ans%i==0&&ans){//把因数除尽
               ans/=i;
           }
       }
   }
   if(ans>1)fac[len++] = ans;//最后剩下一个质因数
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        sum = len = 0;
        scanf("%d",&n);
        for(int i = 0;i<n;i++){
            scanf("%lld",&stone[i]);
            sum+=stone[i];
        }
        Reslove(sum);//分解和的质因数
        LL minn = INF;
        for(int j = 0;j<len;j++){//枚举所有因数
            LL ans = 0;
            for(int i = 0;i<n;i++){
                num[i] = stone[i]%fac[j];//每堆多余石子
                ans+=num[i];
            }
            sort(num,num+n);//排序
            int k = n-1;
            LL moved = 0;
            while(ans>0&&k>=0){//先补大的
                moved+=(fac[j] - num[k]);//移动次数
                ans-=fac[j];//减去已经操作好了的石子数目
                k--;
            }
            minn = min(minn,moved);
        }
        printf("%lld\n",minn);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40772692/article/details/82682965
今日推荐