I - Insurancehttps://vjudge.csgrandeur.cn/problem/AtCoder-arc122_b
1.a[i]>2x,a[i]+x-min(2x,a[i])=a[i]-x;
2.a[i]<2x,a[i]+x-min(2x,a[i])=x;
这题如果x是一个定值,那这题是一个简单题,但x可以随便取。从一般来想,先把a排序,遍历每个ai值,x取a[i]/2(因为这样才知道2x和ai哪个小),a[i]左边的数取x,右边的数取a[i]-x,算出期望,然后遍历取个最小值。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 200000 + 10;
double a[N];
double sum[N];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i];//不用前缀和,直接暴力我觉得也行
double ans = INF;
for (int i = 1; i <= n; i++) {
double x = a[i] / 2;
double t = sum[n] - sum[i] - (n - i - i) * x;//x*i+(n-i)(a[i]-x)
//=(n-i)*a[i]-(n-i)*x+x*i
//=(n-i)*a[i]-(n-i-i)*x
ans = min(ans, t / n);
}
printf("%.6lf\n", ans);
return 0;
}
直接用结论(证明略),x取中间的a[i]/2,这样sum就有可能只等于a中间右边的元素的和,总和才有可能最小( 可以证明,无非就是x=a[0]/2或x=a[n]/2讨论)
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
string s;
int main()
{
double a[100010];
double k;
int i,n;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%lf",&a[i]);
}
sort(a+1,a+1+n);
k=a[(n+1)/2];//取a数组中间的数
double sum=0;
for(i=1;i<=n;i++)
{
sum+=(double)k/2.00000000000+a[i]-min(a[i],k);
}
printf("%.16f",sum/n);
}