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;
    }
  • 相关阅读:
    002变量
    001Java输入、eclipse快捷键
    040同步条件event
    kali配置ip,更新源,更新签名
    039条件变量同步(Condition)
    038信号量
    037多线程同步
    配置java环境变量(详细)
    提高你的Python能力:理解单元测试
    电影里的代码之《机械姬》:筛法求质数
  • 原文地址:https://www.cnblogs.com/mowanying/p/11409070.html
Copyright © 2011-2022 走看看