zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    590. N 叉树的后序遍历
    CF605E
    网络流水题题单
    wqs二分的边界
    luoguP6326 Shopping
    【THUWC2020】工资分配
    CF1336简要题解
    「PKUWC2020」最小割
    洛谷P4895 独钓寒江雪
    省选联考2020简要题解
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308848.html
Copyright © 2011-2022 走看看