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;
}
原文地址:https://www.cnblogs.com/yuhan-blog/p/12308848.html