寒假算法每日一题2022.12.28

寒假算法每日一题2022.12.28

4366. 上课睡觉 - AcWing题库
有 N 堆石子,每堆的石子数量分别为 a1,a2,…,aN。

你可以对石子堆进行合并操作,将两个相邻的石子堆合并为一个石子堆,例如,如果 a=[1,2,3,4,5],合并第 2,3 堆石子,则石子堆集合变为 a=[1,5,4,5]。

我们希望通过尽可能少的操作,使得石子堆集合中的每堆石子的数量都相同。

请你输出所需的最少操作次数。

本题一定有解,因为可以将所有石子堆合并为一堆。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

每组数据第一行包含整数 N。

第二行包含 N 个整数 a1,a2,…,aN。

输出格式
每组数据输出一行结果。

数据范围
1 ≤ T ≤ 10 , 1≤T≤10, 1T10,
1 ≤ N ≤ 1 0 5 , 1≤N≤10^5, 1N105,
0 ≤ a i ≤ 1 0 6 , 0≤ai≤10^6, 0ai106,
∑ i = 1 n a i   ≤ 1 0 6 , \sum_{i=1}^n{ai}\ \leq 10^6, i=1nai 106,
每个输入所有 N 之和不超过 1 0 5 10^5 105

输入样例:

3
6
1 2 3 1 1 1
3
2 2 3
5
0 0 0 0 0

输出样例

3
2
0

样例解释
第一组数据,只需要用 3 个操作来完成:

   1 2 3 1 1 1
-> 3 3 1 1 1
-> 3 3 2 1
-> 3 3 3

第二组数据,只需要用 2 个操作来完成:

   2 2 3
-> 2 5
-> 7

第三组数据,我们什么都不需要做。

解题思路:
我们分析得到,设sum为石子的总数量,cnt能分成每堆石子的数量都相同的石子数量,我们可以知道cnt和分成的堆数都是sum的约数。即 cnt 能整除 sum。因为每次操作只能是相邻的两堆合并,所以操作次数为 初始堆数 - 分成的堆数,即 n - (sum / cnt)。我们要使得操作次数最小,即求符合题意的cnt的最小值。

那么如何确定符合题意的cnt的最小值呢?

我们可以从小到大枚举sum的约数cnt,对与每一个cnt,我们顺序枚举原始石子的堆数,并判断是否能分成每一堆都为cnt。

import java.util.Scanner;

// AcWing4366 上课睡觉
public class Day1228 {
	static final int N = 100010;
	static int[] w = new int[N];
	static int n;
	
	// 判断是否分成每一堆石子数量都为cnt
	public static boolean check(int cnt) {
		for(int i = 0,s = 0; i < n; i++) {
			s+=w[i];
			if(s > cnt) {
				// 出现矛盾,返回false
				return false;
			} else if(s == cnt) {
				s = 0;
			}
			// 这里无需判断s < cnt的情况,因为 cnt为 sum的约数,遍历到最后如果没有矛盾,必然成立
		}
		return true;
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		while(T-- > 0) {
			int sum = 0; // 所有石子的总和
			n = sc.nextInt();
			for(int i = 0; i < n;i++) {
				w[i] = sc.nextInt();
				sum+=w[i];
			}
			// 从大到小枚举可能的堆数(sum的约数),则每一堆石子数量就从小到大枚举
			for(int i = n; i >= 1; i--) {
				if(sum % i == 0 && check(sum/i)) {
					// 操作次数 = n(初始堆数) - i(堆数) 
					System.out.println(n - i);
					break;
				}
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值