zoukankan      html  css  js  c++  java
  • HZOJ 砍树

    考试时打了个暴力T40,正解是整除分块???完全没听过……而且这题居然还有人A了……

    整除分块

    暴力就不说了,直接上正解:


    将d除过去,右边向下取整(显然不能向上取整啊,会超k的)这个不用处理,整除就是向下取整的,然后就用到整除分块的结论了:

    $frac{N}{i}$向下取整,他是一个递减的分段函数,能不能求他每一段的左右端点呢?这样时间复杂度会降好多的。

    对于左端点l,右端点即为$large left lfloor frac N{left lfloor frac Ni ight floor } ight floor$,证明见上面的博客(其实是我不会……),

    回到这个题上,将d除过去,右边向下取整,那么右边的形式就可以用整除分块的结论了,首先第一段的左端点肯定是1,通过式子计算出右端点,考虑式子左边,ai是除l呢,还是除r呢?对于区间[l,r],等式右边是定值,左边单调递减,所以如果r不成立,这一段都不成立,所以除r。

    代码实现(超短):

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    using namespace std;
    LL n,a[110];
    LL k,C;
    signed main()
    {	
    	cin>>n>>k;
    	for(int i=1;i<=n;i++)	
    		cin>>a[i],C+=a[i];
    	C+=k;
    	LL d,r;
    	LL ans=0;
    	for(LL l=1;;l=r+1)
    	{
    		LL tem=0;
    		if(C/(l)<=0)break;
    		r=C/(C/l);
    		for(int i=1;i<=n;i++)	
    			tem+=ceil(1.0*a[i]/r)*r;
    		if(tem<=C)ans=r;
    	}
    	cout<<ans<<endl;
    }
    
  • 相关阅读:
    大一秋学期记录
    韦尼克区受损者如何说话
    暑假训练idea汇总
    高三树洞
    OI回忆录
    NOI2018游记
    收藏
    PKUSC2018游记
    CTSC/APIO2018游记
    Caused by: org.xml.sax.SAXParseException: 外部 DTD: 无法读取外部 DTD 'mybatis-generator-config_1_0.dtd'
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11209326.html
Copyright © 2011-2022 走看看