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

●UOJ 21 缩进优化

时间:2018-01-17 00:28:07      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:复杂度   long   using   inf   names   efi   缩进   方法   body   

题链:

http://uoj.ac/problem/21

题解:

。。。技巧题吧

先看看题目让求什么:

令$F(x)=\sum_{i=1}^{n}(\lfloor a[i]/x \rfloor +a[i]$%$x)$

要求输出最小的F(x)。

首先不难看出,x的取值不会超过最大的a[i]+1,(因为之后的答案都和x==a[i]+1时的答案相同)

把式子化为如下形式:

$F(x)=\sum_{i=1}^{n}(\lfloor a[i]/x \rfloor +(a[i]-\lfloor a[i]/x \rfloor x))$ 

$\quad\quad=\sum_{i=1}^{n}(a[i]-\lfloor a[i]/x \rfloor (1-x))$

$\quad\quad=sum-\sum_{i=1}^{n}(\lfloor a[i]/x \rfloor (1-x))$

$\quad\quad=sum+\sum_{i=1}^{n}(\lfloor a[i]/x \rfloor (x-1))$

现在即是要找出最大的$\sum_{i=1}^{n}(\lfloor a[i]/x \rfloor (x-1))$

然后我们令$t=\lfloor a[i]/x \rfloor$

(把a从小到大排序后)对于每一个枚举的x,

不难发现,随着a[i]的增大,t也是在单增,而且t的取值还是一段一段的。

即对于$a[i]∈ [\lambda x,(\lambda+1)x-1]  $,t的取值都是$\lambda$

所以我们可以用后缀和或者前缀和的方法对于每一个枚举的x,快速求出$\sum_{i=1}^{n}(\lfloor a[i]/x \rfloor (x-1))=\sum_{i=1}^{n}t (x-1)$

使得总复杂度为 O(NlogN)

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 1000050
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
int cnt[MAXN];
int main(){
	int n,maxa=0; long long ans=0,tmp,sum=0;
	scanf("%d",&n);
	for(int i=1,x;i<=n;i++)
		scanf("%d",&x),cnt[x]++,maxa=max(maxa,x),sum+=x;
	for(int i=maxa-1;i;i--) cnt[i]+=cnt[i+1];
	for(int x=1;tmp=0,x<=maxa;x++){
		for(int r=1;r*x<=maxa;r++)
			tmp+=cnt[r*x];
		tmp*=(x-1);
		if(tmp>ans) ans=tmp;
	}
	printf("%lld",sum-ans);
	return 0;
}

  

 

●UOJ 21 缩进优化

标签:复杂度   long   using   inf   names   efi   缩进   方法   body   

原文地址:https://www.cnblogs.com/zj75211/p/8298305.html

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