zoukankan      html  css  js  c++  java
  • 暑假考试题4:砍树 cut(整除分块)

     

    题目:

    分析:

    一看这道题,诶不就二分一个d去O(n)地check不就可以了吗?

    但其实是不能二分的!!因为不满足单调性。比如这组数据:a[ i ]=4  k=1   当d=3时,会在第6天砍,cost=2,d=4时,会在第4天砍,cost=0,明显d更大了,反而更优了!!!

    所以说二分之前一定要考虑是否满足单调性,当自认为满足时,还应该出一点反例(这道题里面出一个小的d不满足,大的反而满足)。

    那么不满足怎么办呢 ->从大到小枚举,枚举到的第一个满足的就break掉。d的上界是 min{ a[ i ] } + k (因为k>=d-minn)

    当然,会T掉。

    于是手推一下式子:

    而ai/d(上取整)会发现有重复的,于是考虑用整除分块 (整除分块的一般证明):如何整除分块

    下面是证明:

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 2100000000
    #define N 105
    #define ll long long
    ll k,minn=inf,ans,a[N],sum;
    int n;
    bool fl[N];
    int main()
    {
        freopen("cut.in","r",stdin);
        freopen("cut.out","w",stdout);
        scanf("%d%lld",&n,&k);
        sum=k;
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i],minn=min(minn,a[i]);
        minn+=k;
        ll d=1;
        while(1){
            ll tot=0;
            for(int i=1;i<=n;i++){
                if(a[i]%d) tot+=(a[i]/d +1)*d;//讨论能不能整除 从而向上取整 
                else tot+=a[i]; 
            }
            if(tot<=sum) ans=d;
            if(d>=minn) break;
            d=sum/(sum/(d+1));
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    php流程控制
    php运算符
    php数据类型
    php基础
    谈谈2019年
    聊聊这三年
    第二次作业(源代码)
    个人介绍
    22.python匿名函数详解
    11.python内置模块之json模块
  • 原文地址:https://www.cnblogs.com/mowanying/p/11409070.html
Copyright © 2011-2022 走看看