zoukankan      html  css  js  c++  java
  • HDU 6237 A Simple Stone Game

    HDU 6237 A Simple Stone Game

    题目大意:

    有n堆石子,每一堆都有ai块。

    每次可以任意将一个石子从一堆移动到另外一堆,代价为1.

    让最后的每一堆石子都是一个质数的倍数(默认0为任何数的倍数)

    求最小代价?

    思路:

    因为如果有一个数x,最后每一堆石子的个数都是它的倍数,那么所有石子的和一定也是x的倍数。

    求每一堆石子的和sum,然后将其分解质因数。

    然后对每一个质因数进行验证。

    怎么验证呢?贪心即可。对每组数取一个x的模。取模之后的数从小到大排序,将少的移动到多的上面。如果再一次到达x,那么最大的堆变成零,多出来的往次大堆上放。

    #include<bits/stdc++.h>
    #define MAXN 100010
    #define ll long long
    using namespace std;
    int n,T,maxx,cnt,cnt2;
    ll sum;
    int a[MAXN],prime[MAXN],cur[MAXN],not_prime[MAXN],Prime[MAXN];
    inline void pre_solve(){
    	not_prime[1]=1;
    	for(int i=2;i<=100000;i++){
    		if(not_prime[i]==0){
    			prime[++cnt]=i;
    		}
    		for(int j=1;j<=cnt&&prime[j]*i<=100000;j++){
    			not_prime[prime[j]*i]=1;
    			if(i%prime[j]==0) break;
    		}
    	}
    }
    inline int ll calc(ll x){
        ll cur_ans=0;
        memcpy(cur,a,sizeof(int)*(n+1));
        for(int i=1;i<=n;i++) cur[i]%=x;
        sort(&cur[1],&cur[n+1]);
        int l=1,r=n;
        while(l<r){
            while(cur[l]%x==0) l++;
            while(cur[r]%x==0) r--;
            int cur_sum=cur[l]%x;
            cur_ans+=cur_sum;
            while((cur[r]+cur_sum)>x){
                cur_sum-=x-cur[r];
                r--;
            }
            cur[r]+=cur_sum;
            l++;
        }
        return cur_ans;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&T);
        pre_solve();
        while(T--){
            sum=0,maxx=0,cnt2=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                sum+=a[i];
                maxx=max(maxx,a[i]);
            }
            long long ans=sum-maxx;
            int pre=2;
            for(int i=pre;i<=(int)sqrt(sum);i++){
                if(not_prime[i]==true||sum%i!=0) continue;
                else{
                    Prime[++cnt2]=i;
                    pre=i;
                    while(sum%i==0) sum/=i;
                }
            }
            // 
            // for(int i=1;i<=cnt2;i++) printf("%d ",Prime[i]); puts("");
            for(int i=1;i<=cnt2;i++){
                ans=min(ans,calc(Prime[i]));
            }
            if(sum!=1) ans=min(ans,calc(sum));
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    CVE-2019-16097:Harbor任意管理员注册漏洞复现
    wfi破解
    Phpstudy隐藏后门
    远程桌面--------ms12-020 漏洞复现 (死亡蓝屏)
    心脏滴血漏洞复现(CVE-2014-0160)
    疑难杂症----克隆虚拟机无法上网
    疑难杂症----Windows10
    mono修改代码模板
    mono for android 各版本下载地址(目前没多大参考价值了,老文章了)
    单独安装VS2012装mono for android
  • 原文地址:https://www.cnblogs.com/fengxunling/p/13667805.html
Copyright © 2011-2022 走看看