Title

CF1898B Milena and Admirer 题解

题目大意

已知有一个长度为 n 的正整数序列 a,现在你可以做若干次以下操作,使得 a 单调不下降:

  • 选择一个 1in
  • 选择一个整数数 1x<ai
  • ai 分成两个正整数 xaix 并重新插入序列中,插入规则如下:
    • 设操作前的序列为 a1,a2,a3,,ai,,ak,操作后的序列为 a1,a2,a3,,x,aix,,ak

解题思路

我们很容易发现,对于所有的 ai,操作后有 x<ai,aix<ai,也就是说,所有的 ai 只能通过操作使得值变小,而不可能增加。那么,我们从后往前更新值。读者自证不难,如果 ai>ai+1,那么把 ai 均分为若干部分使得每部分的值小于 ai+1 且最大是最优决策。

由上可得,我们的操作如下:

  • aiai+1,不做任何操作;
  • ai>ai+1,那么我们把 ai 均分为 cnt=aiai+1,个部分,答案 ans=ans+cnt1,但是这个时候不需要更新 ai 的值,也不需要插入值。接下来,我们把 ai 更新为 aicnt

注意事项

考虑到 ai109,那么 ans 需要开 long long。

AC 代码

码风较丑,不喜勿喷。

#include<math.h>
#include<time.h>
#include<stdio.h>
#include<algorithm>
#define ll long long
#define N 200005
int n,a[N];
inline void work(){
    scanf("%d",&n);ll ans=0;
    for(register int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    for(register int i=n-1;i>=1;--i){
        if(a[i]>a[i+1]){
            int cheu=ceil((a[i]*1.0)/(a[i+1]*1.0));
            int res=a[i]%cheu;ans+=(ll)cheu-1;
            a[i]=a[i]/cheu;
        }else continue;
    }printf("%lld\n",ans);
}signed main(){
    srand(114514);
    srand(rand());
    srand(time(0));
    int T;scanf("%d",&T);
    while(T--) work();
    return 0;
}
posted @   UncleSam_Died  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示