zoukankan      html  css  js  c++  java
  • 【CF830C】Bamboo Partition 分块

    【CF830C】Bamboo Partition

    题解:给你n个数a1,a2...an和k,求最大的d使得$sumlimits_{i=1}^n((d-a[i] \% d) \% d) le k$

    n<=100,a[i]<=10^9,k<=10^11

    题解:$sumlimits_{i=1}^n((d-a[i] \% d) \% d)=dsumlimits_{i=1}^n{lceil {a[i]over d} ceil }-sumlimits_{i=1}^na[i]$

    显然,${lceil {a[i]over d} ceil}$最多只有n*sqrt(maxd)种取值,那么分块处理即可。但是你会发现,$last=lceil{a over {lceil {aover i} ceil}} ceil$得到的是最小的last使得$lceil{aover i} ceil=lceil{aover last} ceil$,所以倒着做即可。

    PS:前几天考试中出了这道题,全场感人的无人AC,有人说这是CFdiv2的F题,感觉莫名其妙~

    如果你熟悉如何用正着分块来处理底的和式,那么想到用倒着分块来处理顶的和式也是自然的~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    int n;
    ll m,ans,a[110],k;
    ll Div(ll x,ll y)
    {
    	return (x+y-1)/y;
    }
    int main()
    {
    	ll i,last,sum,cnt;
    	int j;
    	scanf("%d%I64d",&n,&k);
    	for(j=1;j<=n;j++)	scanf("%I64d",&a[j]),m=max(m,a[j]+k);
    	for(i=m;i;i=last-1)
    	{
    		for(last=1,j=1;j<=n;j++)	last=max(last,Div(a[j],Div(a[j],i)));
    		for(sum=cnt=0,j=1;j<=n;j++)	sum+=(last-a[j]%last)%last,cnt+=Div(a[j],last);
    		if(sum<=k)
    		{
    			printf("%I64d
    ",last+(k-sum)/cnt);
    			return 0;
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    JDBC
    过滤器
    Servlet-web.xml 常见配置
    Servlet-HttpSession接口
    Servlet-Cookie对象
    Servlet-HttpServlet对象
    kmp算法及应用
    线段树入门到自闭
    tarjan算法与拓扑排序
    马拉车模板
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7247598.html
Copyright © 2011-2022 走看看