250
Description
給n個數,你可以合併任意k個數,合併之後出現的數是a[x]+a[y]+...+a[x]/k 。問最後剩下的數字最大是多少
Solution
類似於霍夫曼樹,每次貪心把最小的兩個數合併即可。
Code
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define F first
#define S second
typedef long long LL;
typedef pair<int, int> pii;
const int N = 55;
class MergersDivOne {
public:
double findMaximum(vector <int> revenues) {
int n = revenues.size();
sort(revenues.begin(), revenues.end());
double ans = (revenues[0] + revenues[1]) * 0.5;
for (int i = 2; i < n; ++i) {
ans = (ans + revenues[i]) * 0.5;
}
return ans;
}
};
500
Description:
給n(n≤50 )個骰子,每個骰子的用x個面分別爲1∼x,x≤109 。問同時擲n個骰子,最有可能出現的點數是多少,多解輸出最小值
Solution
不妨考慮兩兩組合,考慮當前可能擲出的點數最大是len,極值點位置是pos,(0-base)。整個圖像應該是先遞增,不變,再遞減。中間不變的地方是極值點。
新來一個骰子,如果len−2∗pos≥dice[i] ,考慮最小的那個極值點的變化,比如和的序列是
1 2 3 4 ,len = 4, pos = 0(極值點爲1)。新來的序列是
3 2 1。顯然新來的序列最右端與pos對齊即產生新的極值點。
如果len−2∗pos<dice[i] ,那麼新極值點就是新列表中間點。
爲了考慮方便,我們將dice數組降序排列。由於考慮的是0-base,最後答案爲pos+n
Code:
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define F first
#define S second
typedef long long LL;
typedef pair<int, int> pii;
class RollingDiceDivOne {
public:
long long mostLikely(vector <int> dice) {
sort(dice.begin(), dice.end(), greater<int>());
LL len = dice[0], pos = 0;
int n = dice.size();
for (int i = 1; i < n; ++i) {
if (len - 2 * pos >= dice[i]) pos += dice[i] - 1;
else pos = (len + dice[i] - 2) / 2;
len += dice[i] - 1;
}
return pos + n;
}
};