您的位置:首页 > 其它

Hello 2018 A - D 题解

2018-01-10 20:12 260 查看
传送门

A, B水题就不说了.

C: 类型 i 的瓶子体积是 2^(i-1),并给出每个瓶子的价钱, 问要得到至少L体积的水最少需要多少钱

首先我们要考虑的就是得到这个i瓶子体积中的水最少需要多少钱. 所以我们前后扫一遍便可得出, 此时我们就有对于每个体积的水我们有了其最少的钱, 那么我们就可以贪心的从大的开始取, 一定是最优的, 然而此时有种情况就是此时瓶子的水直接大于L了, 那么我们取ceil(L/(1<<(i-1)))可能为答案, 还有就是全部恰好组成L也是一种答案, 所以最后我们的答案就是在这些答案中的最小值.

AC Code

int a[50];
void solve()
{
int n, L;
while(cin >> n >> L) {
for (int i = 1 ; i <= n ; i++) cin >> a[i];
for (int i = 1 ; i <= n-1 ; i++) {
if (a[i]*2 < a[i+1]) a[i+1] = 2*a[i];
}
for (int i = n ; i >= 2 ; i--) {
if (a[i] < a[i-1]) a[i-1] = a[i];
}
// 得到每个体积的水最少花的钱
ll ans = 0,res = INF;
for (int i = n ; i >= 1 ; i--) {
ans += 1ll*L/(1 << (i-1))*a[i];
res = min(res, ans + a[i]);  // 在这些答案中取一个最小的,
L %= (1 << (i-1));
}
res = min(res, ans);
cout << res << endl;
}
}


D: 现在有n个问题, 考试时间为T, 每道题有难度ai, 以及解决这道题的时间ti, 如果对于没到解决了的题其难度数 >= 总的解题数, 那么就得一分, 问最多可以得多少分.

首先我们考虑, 如果解决一道题, 它并不能使我们的答案变大, 那么这道题也就没有意义. 所以我们考虑有意义的这些题. 假设我们知道最后我们的得分k,那么对于ai >= k, 则就是我们满足的, 所以我们只需要check一下是否有k个这样的问题使得其难度数ai >= k ,当然我们要对解决这些问题的时间从小到大排个序. 如果有的话, 则此时的k就可以作为答案之一. 所以我们当然直接二分答案就行啦, 然后for一遍check一下就行了.

AC Code

const int maxn = 2e5+5;
int cas=1;
int n, T;
struct node {
int a,t,id;
bool operator < (const node& x) const {
return t < x.t;
}
}s[maxn];
int res[maxn], cnt = 0;
bool check(int x) {
cnt = 0;
int tot = 0 ;
for (int i = 1 ; i <= n ; i++) {
if (s[i].a < x) continue;
tot += s[i].t;
if (tot > T) break;
res[++cnt] = s[i].id;
}
return cnt >= x;
}
void solve()
{
while(cin >> n >> T) {
for (int i = 1 ; i <= n ; i ++) {
int a, b;
cin >> a >> b;
s[i] = node{a, b, i};
}
sort(s+1, s+1+n);
int l = 0, r = n , mid, ans = 0;
while(r >= l) {
mid = (l + r) >> 1;
if (check(mid)) {
l = mid + 1;
ans = mid;
}
else r = mid - 1;
}
check(ans);   //因为我们每次check使得res数组都在变, 所以最后我们需要答案就应该还要扫一遍.
cout << ans << endl << ans << endl;
if (!ans) cout << endl;
for (int i = 1 ; i <= ans ; i ++) {
printf("%d%c", res[i], i == ans ?'\n':' ');
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: