Send Boxes to Alice (Hard Version)
給定,求使 的最小花費,其中,k是sum的因子。
顯然的,如果,且,則時,答案小於時的答案。
所以,枚舉因子的時候可以不用枚舉因子k的倍數。
所以,題意就是將a中的某一小段中的所有數字加到其中的一個點上,花費爲
顯然,從左到右,一段區間和大於k,那麼這一段區間必然要匯合成一個點。
該段區間花費最小時,匯合的點m座標滿足:
顯然,m取其他值時,答案更大。
,sum不同因子數最多爲12個。
如何快速計算一個確定的k的答案:
當i<m時,
當i=m時,
當i>m是,
for(int i=l;i<=r;++i){
s=(s+a[i])%k;
res+=min(s,k-s);
}
代碼:
#include<bits/stdc++.h>
using namespace std;
char buf[1<<20],*P1=buf,*P2=buf;
#define gc() (P1==P2&&(P2=(P1=buf)+fread(buf,1,1<<20,stdin),P1==P2)?EOF:*P1++)
#define TT template<class T>inline
TT bool read(T &x){
x=0;char c=gc();bool f=0;
while(c<48||c>57){if(c==EOF)return 0;f^=(c=='-'),c=gc();}
while(47<c&&c<58)x=x*10+c-48,c=gc();
if(f)x=-x;return 1;
}
TT bool read(T&a,T&b){return read(a)&&read(b);}
TT bool read(T&a,T&b,T&c){return read(a)&&read(b)&&read(c);}
typedef long long ll;
#define Init(a,v) memset(a,v,sizeof(a))
#define lowbit(x) (x&(-x))
const ll MAXN=1e6+8,mod=1e9+7,inf=0x3f3f3f3f;
ll n,a[MAXN],s;
ll solve(ll k){
ll pre=0,res=0;
for(int i=1;i<=n;++i)(pre+=a[i])%=k,res+=min(pre,k-pre);
return res;
}
int main() {
read(n);
for(int i=1;i<=n;++i){
read(a[i]);
s+=a[i];
}
if(s<=1){printf("-1");return 0;}
ll ans=1ll<<62,k;
for(k=2;k*k<=s;++k){
if(s%k)continue;
while(s%k==0)s/=k;
ans=min(ans,solve(k));
}
if(s>1)ans=min(ans,solve(s));
printf("%I64d",ans);
return 0;
}