Codeforces Round #494 (Div. 3)

get

  • 高效位运算 * __builtin _ __builtin_ll(函数名后加ll表示longlong)*
    • __builtin_ffs(unsigned int x) 返回x最后一个1是从右往左第几位
    • __builtin_clz(unsigned int x) 返回x前导零的个数
    • __builtin_ctz(unsigned int x) 返回后面零的个数
    • __builtin_popcount(unsigned int x) 返回二进制1的个数

A. Polycarp’s Pockets

题意

将一堆硬币分配到不同的口袋,相同的硬币不能放到一个口袋,问最少需要多少个口袋

AC

  • 答案就是相同硬币数量的最大值
#include 
#define N 5005
#define ll long long
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
int main() {
    // freopen("in.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    vector<int> sum(105);

    for (int i = 0; i < n; ++i) {
        int x;
        scanf("%d", &x);
        ++sum[x];
    }
    sort(sum.begin(), sum.end(), [&](const int &a, const int &b){
        return a > b;
    });
    cout << sum[0] << endl;

}

B. Binary String Constructing

题意

给定a, b, x; 构造长度为(a + b)的“01”串,满足里面一共有x个 (si ≠ si + 1),例如“010100”共有4个

AC

  • 可以得出满足X个需要长度为(x + 1)的“01”串,先构造满足x的“01”串让后将剩下的“0” 和 “1” 加入到不影响的位置
#include 
#define N 5005
#define ll long long
#define mem(a, b) memset(a, b, sizeof(a))

using namespace std;
int main() {

    // freopen("in.txt", "r", stdin);
    int a, b, x;
    string t, ans;
    scanf("%d%d%d", &a, &b, &x);
    // 构造满足X的“01”串
    if (a > b)  t = "01";
    else        t = "10";
    ++x;
    int sum = x / 2;
    for (int i = 0; i < sum; ++i) {
        ans += t;
    }
    a -= sum;
    b -= sum;
    if (x % 2) {
        if (t == "01")  ans += "0", --a;
        else            ans += "1", --b;
    }
    // 将剩下的“0” “1” 加上
    int len = ans.size();
    int l = ans.find('0');
    if (a)  ans.insert(l, a, '0');
    int r = ans.find("1");
    if (b)  ans.insert(r, b, '1');
    cout << ans << endl;
}

C. Intense Heat

题意

给N个整数,求最大的连续数的平均数,连续数大于等于K

AC

  • 暴力
#include 
#define N 5005
#define ll long long
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
int main() {
    // freopen("in.txt", "r", stdin);
    int n, k;
    scanf("%d%d", &n, &k);
    vector<int> v(n + 1);
    vector<int> sum(n + 1);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &v[i]);
        sum[i] = sum[i - 1] + v[i];
    }
    double ans = 0;
    for (int i = k; i <= n; ++i) {
        for (int j = i; j <= n; ++j) {
            double t = (sum[j] - sum[i - k]) * 1.0 / (j - i + k);
            if (t - ans > 1e-6) ans = t;
        }
    }
    printf("%.15lf\n", ans);
}

D. Coins and Queries

题意

给你N个硬币,每个硬币的价值是2的次方,一共Q次询问,每次询问给定X,求构成X最少需要多少个硬币,如果不能构成输出-1

AC

  • 先将给定的硬币的二进制位数统计下,每次处理X时,从高位向下贪心,如果最后X的值大于0,则为-1
#include 

using namespace std;
int main() {
    // freopen("in.txt", "r", stdin);
    int n, q;
    scanf("%d%d", &n, &q);
    vector<int> v(33);

    // 可用++v[__builtin_ctz(x)] 代替
    for (int i = 0; i < n; ++i) {
        int x;
        scanf("%d", &x);
        int sum = 0;
        while (x) {
            ++sum;
            x /= 2;
        }
        ++v[sum - 1];
    }

    for (int i = 0; i < q; ++i) {
        int x, ans = 0;
        scanf("%d", &x);
        for (int j = 31; j >= 0; --j) {
            if (v[j] && (1 << j) <= x) {
                int sum = x / (1 << j);
                if (v[j] < sum) sum = v[j];
                ans += sum;
                x -= (1 << j) * sum;
            }
            if (x == 0) break;
        }

        if (x > 0)  ans = -1;
        printf("%d\n", ans);
    }

}
#include 

using namespace std;
int main() {

    // freopen("in.txt", "r", stdin);
    int n, q;
    scanf("%d%d", &n, &q);
    vector<int> v(33);

    // ++v[__builtin_ctz(x)] 代替
    for (int i = 0; i < n; ++i) {
        int x;
        scanf("%d", &x);
        ++v[__builtin_ctz(x)];
    }

    for (int i = 0; i < q; ++i) {
        int x, ans = 0;
        scanf("%d", &x);
        for (int j = 31; j >= 0; --j) {
            int need = min(x >> j, v[j]);
            ans += need;
            x -= (1 << j) * need;
        }

        if (x > 0)  ans = -1;
        printf("%d\n", ans);
    }

}

你可能感兴趣的:(练习)