您的位置:首页 > 汽车 > 时评 > 细胞分裂题解

细胞分裂题解

2024/9/8 8:42:33 来源:https://blog.csdn.net/mikeshizi1234/article/details/140613706  浏览:    关键词:细胞分裂题解
细胞分裂

简化题意:将数组中任何一个元素替换为任意两个和为该元素的数字。将数组变成元素按非递减顺序排列的数组,所需的最少操作次数。

思路概述:这道题我认为就是一个贪心加数学的题目,因为题目要求所有操作过后,除最后一个数外,每个数都不大于后一个数。因此一个数越大,留给前面的数的空间才越多。所以得到贪心结论:最后一个数不拆。

那样根据我们得出的第一个结论,从后往前推,那么不妨设当前这个数字是 x ,它的后一位是 y 。那么久就只有这三种情况。

  • 若 x \leq y ,根据贪心,我们不应该拆分了,已经满足了。

  • 若 x>y ,我们需要拆分 x 使得拆分后的最大值不超过 y ,而且根据贪心,拆分后的最小值要尽可能的大,那我们设 (k-1) \times y<x \leq k \times y (也就是说 k=\left \lceil \frac{x}{y} \right \rceil ),但是我们根据抽屉原理不难得出 x 至少要被拆分成 k 份,不然最大值一定会超过 y 。但是因为拆的次数越少,而且拆的平均才可能让这个值尽可能地大。因此我们对 x 进行 (k-1) 次拆分把它变成 k 个数。其中的最小值呢,就是 k=\left \lfloor \frac{x}{k} \right \rfloor 。

  • 若 x=y ,什么也不用动,最好的情况。

#include<bits/stdc++.h>
using namespace std;
int n;
int a[100005];
int main()
{cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}long long ans=0;int last=a[n];//维护反向枚举中遇到的最小值(包括拆分之后的)for(int i=n-1;i>0;i--){if(a[i]>last){int cnt=ceil((double)a[i]/last);//一共要分成几个数ans+=cnt-1;//统计拆分次数last=a[i]/cnt;//切分后的最小值为a[i]/cnt(无论是否能整除)}else if(a[i]<last)//不需要拆分维护最小值{last=a[i];}//剩下的哪一类不用管。}cout<<ans<<endl;return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com