[Codeforces1254B]Send Boxes to Alice

題意

nn盒排成一列的糖果盒,第ii盒有aia_i個糖果

每次可以取出某一盒一顆糖果放到相鄰的糖果盒裏

問使得所有盒子的裏的糖果數均能被某個k(k>1)k(k>1)整除的最少移動次數


題解

設糖果總數的SumSum(顯然Sum=1Sum=1無解)

符合條件的kk一定滿足kSumk\mid Sum

考慮對於一個kk如何求解最少的移動次數

首先肯定要將所有的aia_ikk取餘

對於一個aia_i可以將aia_i顆糖果全部向後挪,於是ai+1=(ai+1+ai)mod  ka_{i+1}=(a_{i+1}+a_i)\mod k

也可以從後面挪kaik-a_i顆糖果到aia_i上,於是ai+1=ai+1(kai)ai+1+aimod  ka_{i+1}=a_{i+1}-(k-a_i)\equiv a_{i+1}+a_i \mod k

Si=k=1iaimod  kS_i=\sum_{k=1}^ia_i \mod k,那麼Ans=i=1nmin(Si,kSi)Ans=\sum_{i=1}^n\min(S_i,k-S_i)

通過上面可以發現如果如果k1Sum,k2Sumk_1\mid Sum,k_2\mid Sum,且k=k1k2Sumk=k_1k_2\mid Sum

那麼kk的答案一定不會比k1,k2k_1,k_2優,所以只需要枚舉SumSum的質因子即可

題目當中Sum1012Sum\le10^{12},而2×3×5××37>10122\times3\times5\times\ldots\times37>10^{12},所以計算次數不會太多

時間複雜度爲O(n×SumO(n\times Sum質因子個數+Sum)+\sqrt{Sum})

using ll=long long;
inline ll Calc(ll p){
	ll Cnt=0,Tmp=0;
	for(int i=1;i<=n;++i)
		Cnt=(Cnt+a[i])%p,Tmp+=min(Cnt,p-Cnt);
	return Tmp;
}
inline void Sol(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",a+i),Sum+=a[i];
	if(Sum<2)
		return(void)puts("-1");
	Ans=-1ull>>1;
	for(int i=2;(ll)i*i<=Sum;++i)
		if(Sum%i==0){
			while(Sum%i==0)Sum/=i;
			Ans=min(Ans,Calc(i));
		}
	if(Sum>1)
		Ans=min(Ans,Calc(Sum));
	printf("%d\n",Ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章