NC50038 kotori和糖果


NC50038 kotori和糖果

题目

题目描述

kotori共有 /(n/) 块糖果,每块糖果的初始状态是分散的,她想把这些糖果聚在一堆。但她每次只能把两堆糖果合并成一堆。

已知把两堆数量为 /(a/) 和 /(b/) 的糖果聚在一堆的代价是 /(|a-b|/) 。

kotori想知道,她把这 /(n/) 块糖果聚在一堆的最小代价是多少?

输入描述

第一行是一个正整数 /(T/) ,代表数据组数。

第二行到第 /(T+1/) 行,每行一个非负整数 /(n/) ,代表kotori的糖果总数量。

输出描述

每行一个整数,代表kotori需要花费的最小代价。

示例1

输入

2
5
6

输出

2
2

说明

n=5时,kotori可以这样聚集糖果:

1 1 1 1 1

2 1 1 1

2 2 1

2 3

5

每一步的代价分别是0,0,1,1,总代价为2。

备注

对于 /(50/%/) 的数据,/(0<T≤100000, 0≤n≤100000/)

对于另外 /(50/%/) 的数据,/(T=1 , 0≤n≤10^{18}/)

题解

思路

知识点:贪心,分治。

显然,每次合并如果两堆糖果数量刚好是合并后总数一半的时候代价最小。

用 /(map/) 记忆化搜索,注意 /(n=0/) 的情况特判。

时间复杂度 /(O(n)/)

空间复杂度 /(O(n)/)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

map <ll, ll> mp;

ll dg(ll n) {
    if (n <= 1) return 0;
    if (mp.count(n)) return mp[n];
    if (n & 1) return mp[n] = dg(n >> 1) + dg((n >> 1) + 1) + 1;
    else return mp[n] = dg(n >> 1) << 1;
}

bool solve() {
    ll n;
    cin >> n;
    cout << dg(n) << '/n';
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        if (!solve()) cout << -1 << '/n';
    }
    return 0;
}

原创文章,作者:3628473679,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/270135.html

(0)
上一篇 2022年6月24日 04:38
下一篇 2022年6月24日 04:38

相关推荐

发表回复

登录后才能评论