码迷,mamicode.com
首页 > 其他好文 > 详细

【CF830C】Bamboo Partition 分块

时间:2017-08-30 11:02:40      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:考试   sum   def   font   cpp   class   names   art   ast   

【CF830C】Bamboo Partition

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

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

题解:$\sum\limits_{i=1}^n((d-a[i] \% d) \% d)=d\sum\limits_{i=1}^n{\lceil {a[i]\over d}\rceil }-\sum\limits_{i=1}^na[i]$

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

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\n",last+(k-sum)/cnt);
			return 0;
		}
	}
	return 0;
}

 

【CF830C】Bamboo Partition 分块

标签:考试   sum   def   font   cpp   class   names   art   ast   

原文地址:http://www.cnblogs.com/CQzhangyu/p/7247598.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!