KS 2018 Round A:第二题

在这里插入图片描述
在这里插入图片描述

这一题我快做出阴影了,当然题目不好做,我看了别人的讲解才做出来,但是自己实现的时候各种狗屁错误,我tm。。。

本题做法:
E(k):表示可以redip k次的最优期望。
E(0) = sum(Vi) / N
E(k): 如果取出的v > E(k-1),那么留下;否则redip。
转移方程为:E(k) = (smallerCount * E(k-1) + largerSum) / N;这里的small large是相对于dp[k-1]说的。
所以这里要使用二分查找,而且的话使用前缀和来很快地知道大于部分的和。

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>

using namespace std;

double helper(vector<int>& nums, int K);

int main() {
    int T;
    cin >> T;
    int cnt = 0;
    while (++cnt <= T) {
        int N, K;
        cin >> N >> K;
        vector<int> nums;
        int num;
        while (N-- > 0) {
            cin >> num;
            nums.push_back(num);
        }
        double res = helper(nums, K);
        //cout << "Case #" << cnt << ": " << res << endl;
        printf("Case #%d: %f\n", cnt, res);
    }
}

double helper(vector<int>& nums, int K) {
    int sz = nums.size();
    vector<double> dp(K+1, 0.0);//注意是K的大小
    sort(nums.begin(), nums.end());
    vector<long long> sums(sz, 0);
    sums[sz-1] = nums[sz-1];
    for (int i = sz-2; i >= 0; --i)
        sums[i] = sums[i+1] + nums[i];
    dp[0] = ((double)sums[0]) / sz;
    for (int i = 1; i <= K; ++i) {
        auto iter = upper_bound(nums.begin(), nums.end(), dp[i-1]);
        int cnt = iter - nums.begin();
        dp[i] = (cnt*dp[i-1] + (cnt == sz ? 0 : sums[cnt])) / sz;
    }//注意cnt超出范围,在尾后的位置的情况

    return dp.back();
}

解法简单明了,但是自己实现的时候各种错误(比如dp的大小一开始设置为了sz等等),需要之后一直注意的几个问题有:
1.可以使用upper_bound, lower_bound, 以及binary search 来进行二分查找,含义和map的函数是一样的(https://www.cnblogs.com/Tang-tangt/p/9291018.html)。但是需要注意的一点是:upper_bound, lower_bound,它们返回的位置可能是尾后的位置,所以数组可能会越界。我一开始就是犯了这个错误,导致卡住,而且这种越界的错误最难排查,累死我了。
2.如果容器底层是连续内存的话,可以使用迭代器加减。
3.另外,对于kickstart,如果输出的是小数,那么就得用printf(#include < cstdio >)。可以看我注释掉的那一行,用cout输出就是错的,用printf就是对的,即使没有保留几位小数,但还是有用。

今天一晚上做了一题,我真的是fuck了。但是也收获不少吧,更多的是感觉ks好像没我想象的那么难,确实比平时lc做的要难,但是也有意思很多,也不是自己想不出来的那种,无非是:1.这种题目不熟悉2.这里码代码和lc上不太一样,不太适应。自己熟悉和适应之后是可以独立完成的ks的。

posted @ 2019-11-01 21:41  于老师的父亲王老爷子  阅读(13)  评论(0编辑  收藏  举报