EC-final2017 B - Scapegoat Gym - 101775B(贪心)

Aori is very careless so she is always making troubles. One day she does it again, with N big troubles! But this time she seems to be at ease because she has found M Inklings to take all the blames. Each trouble can be measured by a severity number ai. Each trouble needs at least one Inkling to take the blame, and each Inkling can help Aori to take the blame for exactly one trouble. If two or more Inklings take the same trouble, they will take this blame together and discuss how to divide this trouble into… some trivial things… to reduce the pressure on each Inkling, as long as the total severity on Inklings is equal to the severity of this trouble.

Inklings are so warm so that Aori wants to think a way to let the variance of severity on each Inkling to be minimal. Could you help Aori make her scapegoats?

Formally, the variance of variables is the expectation of the squared deviation of a variable from its mean:

Input
The first line of the input gives the number of test cases, T. T test cases follow.

For each test case, the first line contains two integers N and M, where N is the number of troubles, and M is the number of Inklings. The next line contains N integers a1, a2, …, aN representing the severity of the troubles that Aori makes.

1 ≤ T ≤ 100.
1 ≤ N ≤ M ≤ 2 × 105.
1 ≤ ai ≤ 10000.
.
Output
For each test case, output one line containing “Case #x: y”, where x is the test case number (starting from 1) and y is the minimal variance.

y will be considered correct if it is within an absolute or relative error of 10 - 8 of the correct answer.

Example
Input
3
3 6
1 2 3
5 10
5 6 7 8 9
6 6
1 1 4 5 1 4
Output
Case #1: 0.000000000000
Case #2: 0.400000000000
Case #3: 2.888888888889
Note
For the first sample, Aori can let one Inkling to take the first trouble’s blame, two Inklings for the second, and three Inklings for the third. The severity on each Inkling is 1 unit, so their variance should be 0.

题意:
有n堆东西,m个人来分。第 i 堆有k个人的话,这堆里每个人贡献为a[i] / k。
每堆至少一个人,每人只能有一堆。
求一种分配方式使得每个人贡献值所得方差最小。

思路:
首先每堆至少分配一个人,那就先分配一个人。然后剩下的人去找自己的堆。找哪堆呢?
注意到,平均值是固定的。那么每堆加入一个数造成的方差变化也是固定的。我们维护这个变化值,每次取出变化值最大的堆加人,意味着方差值减少最多。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

struct Node
{
    int x;
    double num;
    double val;
    bool operator < (const Node &rhs)const
    {
        return val < rhs.val;
    }
};

priority_queue<Node>q;
double a[200005];
double avg;

double sqr(double x)
{
    return x * x;
}

double cal(Node now)
{
    double x = now.x;
    double tmp1 = sqr((now.num / x - avg)) * x;
    double tmp2 = sqr((now.num / (x + 1) - avg)) * (x + 1);
    return tmp1 - tmp2;
}

int main()
{
    
    int T;scanf("%d",&T);
    int kase = 0;
    while(T--)
    {
        int n,m;scanf("%d%d",&n,&m);
        double sum = 0.0;
        
        for(int i = 1;i <= n;i++)
        {
            scanf("%lf",&a[i]);
            
            
            sum += a[i];
        }
        avg = sum / m;
        for(int i = 1;i <= n;i++)
        {
            Node now;
            now.x = 1;now.num = a[i];now.val = cal(now);
            q.push(now);
        }
        Node now;
        now.x = 1;now.num = 1;
        double ans = 0;
        for(int i = 1;i <= m - n;i++)
        {
            Node now = q.top();q.pop();

            now.x++;now.val = cal(now);
            Node t;
            t.x = 2;t.num = 3;
            
            q.push(now);
        }
        while(!q.empty())
        {
            Node now = q.top();q.pop();
            ans += now.x * sqr(avg - now.num / now.x);
        }
        printf("Case #%d: %.8f\n",++kase,ans / m);
    }
    return 0;
}

发布了594 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/103517309
今日推荐