列表

详情


NC212068. 最优公式

描述

有一个长为 n 的数组
你需要找到两个实数 a, b,使得 尽可能小。
求出这个最小值。
容易发现答案乘上 2 一定是整数,求出答案乘上 2 模 的值。

输入描述

第一行一个整数 n。
接下来一行 n 个整数 

输出描述

输出一个整数,表示答案乘上 2 模  的值。

示例1

输入:

2
1 2

输出:

4

说明:

a = b = \frac{3}{2} 时最优。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 74ms, 内存消耗: 888K, 提交时间: 2020-09-22 11:37:49

#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int N=1e5+9;
const ll mo=1e9+7;
int n,a[N],l,r,mid;
ll m,s;
ll cnt(int p)
{
	ll s=0; int j=1;
	while(j<n&&a[1]+a[j]<=p) j++;
	fo(i,1,n)
	{
		while(j&&a[i]+a[j]>p) j--;
		s+=j;
	}
	return s;
}
int main()
{
	cin>>n; m=1ll*n*n+1>>1;
	fo(i,1,n) cin>>a[i];
	sort(a+1,a+n+1);
	for(l=a[1]*2,r=a[n]*2;l<r;)
	{
		mid=l+r>>1; ll t=cnt(mid);
		t>=m?r=mid:l=mid+1;
	}
	fo(i,1,n) a[i]=abs(a[i]*2-l);
	sort(a+1,a+n+1);
	fo(i,1,n) s=(s+a[i]*(2*i-1ll))%mo;
	cout<<s;
}

C++11(clang++ 3.9) 解法, 执行用时: 395ms, 内存消耗: 1256K, 提交时间: 2020-09-24 09:42:48

#include<bits/stdc++.h>
using namespace std;

const int N=100010;
int a[N],n,b[N];

long long check(int x){
	long long ans=0;
	for(int i=1;i<=n;i++) b[i]=abs(a[i]-x);
	sort(b+1,b+1+n);
	for(int i=1;i<=n;i++) ans+=1ll*b[i]*(i+i-1);
	return ans;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]*=2;
	sort(a+1,a+1+n);
	int L=a[1],R=a[n];
	while(L<R){
		int mid1=L+(R-L)/3,mid2=R-(R-L)/3;
		if(check(mid1)<check(mid2)) R=mid2-1;
		else L=mid1+1;
	}
	printf("%lld\n",check(L)%1000000007);
}

上一题