• Codeforces 1255E1


    思路:

    1.因为所有盒子里要么是0要么是1,因此我们对一个是1的盒子做的操作是移动或者不移动;
    2.首先计算所有盒子里总的巧克力个数ans,首先明白题目中的k需要是一个质数且k就是盒子里的巧克力个数,这样才能保证移动的次数最少;
    3.我们可以使用埃氏筛法算出[2,ans]内的所有质数,然后依次遍历,若该数i能被ans整除,则可以分成ans/i个带有i个巧克力的盒子;因为要使移动次数最少,利用贪心的思想我们可以得知从第一个有巧克力的盒子开始,每i个带有巧克力的盒子移到一起,且移动到它们最中间的那个盒子;
    4.每个i都可以算出一个移动次数,取所有移动次数里最小的那个即是答案(若ans<2,答案是-1);

    代码:

    #define IOS ios::sync_with_stdio(false)
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    #define pb(a) push_back(a)
    #define rp(i,n) for(int i=0;i<n;i++)
    #define rpn(i,n) for(int i=1;i<=n;i++)
    const int MAX_N=1e5+99;
    int prime[MAX_N];      //存放第i个素数,i从0开始 
    bool is_prime[MAX_N];  //is_prime[i]为true表示i是素数 
    int sieve(int n){      //返回n以内素数的个数 
    	int p=0;
    	for(int i=0;i<=n;i++) is_prime[i]=true;
    	is_prime[0]=is_prime[1]=false;
    	for(int i=2;i<=n;i++){
    		if(is_prime[i]){
    			prime[p++]=i;
    			for(int j=2*i;j<=n;j+=i) is_prime[j]=false;
    		}
    	}
    	return p;
    }
    vector<LL> v;
    int main(){
    	IOS;
    	LL n;
    	cin>>n;
    	int ans=0;
    	for(LL i=0;i<n;i++){
    		int a;
    		cin>>a;	
    		if(a){
    			ans++;
    			v.pb(i);
    		}	
    	}
    	int num=sieve(ans);
    	LL min_c=LLONG_MAX;
    	rp(pos,num){
    		int a=prime[pos];
    		if(ans%a) continue;
    		LL cost=0;
    		for(int i=0;i<v.size();i+=a){
    			int pos=i+(a>>1);
    			int end=i+a;
    			for(int j=i;j<end;j++) cost+=1ll*abs(v[j]-v[pos]);
    		}
    		min_c=min(cost,min_c);
    	}
    	if(ans<2) cout<<-1;
    	else cout<<min_c;
    	return 0;
    }
    
  • 相关阅读:
    解决“google快照无法打开”的简单而有效的方法~
    在Struts2里面嵌入Spring
    HDU
    设计模式大总结(二)
    Node.js入门笔记
    草图检索和识别[开源]
    2019-10-31-VisualStudio-断点调试详解
    2019-10-31-VisualStudio-断点调试详解
    2019-9-2-C#-设计模式-责任链
    2019-9-2-C#-设计模式-责任链
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308849.html
Copyright © 2020-2023  润新知