思路:
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;
}