AcWing 4366. 上课睡觉

AcWing 4366. 上课睡觉

原题

题目链接

有 N堆石子,每堆的石子数量分别为 a1,a2,…,aN1,2,…,。

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

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

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

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

输入格式

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

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

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

输出格式

每组数据输出一行结果。

数据范围

1≤T≤10^10,
1≤N≤10^5,
0≤ai≤10^6,

∑i=1~n ai≤10^6,
每个输入所有 N 之和不超过 10^5。

输入样例:
3
6
1 2 3 1 1 1
3
2 2 3
5
0 0 0 0 0
输出样例:
3
2
0
样例解释

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

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

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

   2 2 3
-> 2 5
-> 7

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

正确题解

# AcWing 4366. 上课睡觉
T=int(input())
lisyue=[]

for i in range(0,T):
    lenth=int(input())
    lis=input().split(' ')
    lisn=[int(num) for num in lis]
    lissum=sum(lisn)
    liscount=[]
    for i in range(1,lissum+1):
        if lissum%i==0:
            liscount.append(i)
    yueshu=0
    for count in liscount:
        psum=0
        for item in lisn:
            psum+=item
            if psum<count:
                flag=0
            elif psum==count:
                flag=1
                psum=0
            else:
                flag=0
                break
        if flag==1:
            yueshu=count
            break
    if yueshu==0:
        lisyue.append(0)
        continue
    lisyue.append(lenth-lissum/yueshu)
for i in lisyue:
    print(int(i))

解题思路

  • 1.最终得到的结果每堆的总和一定是那一行N个数字的约数count,所以只要将一个连续的序列(输入的N个数),划分成若干段,每段和=count即可,最后需要操作的次数=n-N个数的sum/count(因为要最小的操作次数,所以count越小越好)
  • 2.特殊处理:如果那一段的和为0(则没有约数,sum=0,count=null),则直接需要合并次数=0,因为a_i大于=0,如果等于0则说明那一段的都是0
  • 3.如何划分?可以从前往后遍历每一段,如果段和小于count则继续往后走,大于count则说明这个约数不能满足条件,换成下一个count
  • 4.这个能直接遍历而不会超时的原因:一般时间要求控制在12秒,即操作次数控制在10^7108,而每一行的数字总数小于105,和为10^6以内的最多的约数个数为240个,所以不会超时
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值