hdu6237 分解质因子

题意:给一堆石子,每次移动一颗到另一堆,要求最小次数使得,所有石子数gcd>1

题解:枚举所有质因子,然后找次数最小的那一个,统计次数时,我们可以事先记录下每堆石子余质因子 的和,对所有石子取余,sort,从后往前扫(这样做的原因是取余后的数组只有可能有三种,排序之后最后的就是最大的,加上质因子减去石子数就是使这堆石子加上一些石子,然后又因为,可以有多堆石子放到同一堆里,那么这样处理就是可行的),每次加了之后总和减去质因子,如果总和小于0,那么就退出

ps:这题的难点不在于分解质因子,而在于找最小次数。

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-12;
const int N=100000+10,maxn=90000+10,inf=0x3f3f3f3f;

ll a[N],b[N];
int n;
ll solve(ll x)
{
    ll sum=0,ans=0;
    for(int j=1;j<=n;j++)
    {
        b[j]=a[j]%x;
        sum+=b[j];
    }
    sort(b+1,b+1+n);
    for(int i=n;i>=1;i--)
    {
        if(!b[i])continue;
        ans+=x-b[i];
        sum-=x;
        if(sum<=0)break;
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        ll sum=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%lld",&a[i]);
            sum+=a[i];
        }
        ll res=1e18;
        for(ll i=2; i*i<=sum; i++)
        {
            if(sum%i==0)
            {
                res=min(res,solve(i));
                while(sum%i==0)sum/=i;
            }
        }
        if(sum!=1)
        {
            res=min(res,solve(sum));
        }
        printf("%lld
",res);
    }
    return 0;
}
/********************

********************/
View Code
原文地址:https://www.cnblogs.com/acjiumeng/p/7826046.html