• Spices(线性基、贪心)


    题意

    \(2^n-1\)个数字,分别是\(1,2,\dots,2^n-1\)。它们具有权值,分别为\(c_1,c_2,\dots,c_{2^n-1}\)

    从这些数字中选择一些数字组成集合\(S\),对于\(1,2,\dots,2^n-1\)中任意一个数字\(i\),都可以从\(S\)中找到一个子集,使得子集里面所有数异或起来为\(i\)

    问:集合\(S\)中所有数之和的最小值为多少?

    数据范围

    \(2 \leq n \leq 16\)

    思路

    线性基模板题。

    首先不考虑权值的问题,只考虑集合\(S\)如何得到。这个问题为线性基的基本应用,只需要在插入的过程中,记录当前元素是否使用了即可。

    现在考虑权值,只需要在上面的基础上,对权值进行排序即可(因为在\(b\)数组的构造过程中,肯定是优先选择权值小的数)。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<ll, int> pii;
    
    const int N = 20;
    
    int n;
    pii a[1 << N];
    ll b[N];
    ll ans;
    
    void ins(int x, ll val) //插入数字,获取线性基
    {
        for(int i = 15; i >= 0; i --) {
            if(x >> i & 1) {
                if(!b[i]) {
                    b[i] = x;
                    ans += val;
                    return;
                }
                else x ^= b[i];
            }
        }
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i < (1 << n); i ++) {
            ll x;
            scanf("%lld", &x);
            a[i] = {x, i};
        }
        sort(a + 1, a + (1 << n));
        for(int i = 1; i < (1 << n); i ++) {
            ins(a[i].second, a[i].first);
        }
        printf("%lld\n", ans);
        return 0;
    }
    
  • 相关阅读:
    JS 使用 html2canvas 将页面转PDF
    代码记录
    js 原生图片批量上传 multiple="multiple"
    Go中的HTTP debug技能
    位运算 交换2个数 异或运算
    记一次 JMeter 压测 HTTPS 性能问题 拂衣 阿里云云栖号 20220527 19:00 发表于北京
    RVA relative virtual address PE
    进制
    浏览器是不允许页面直接读取本地硬盘资源的
    四平方和定理
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16013957.html
Copyright © 2020-2023  润新知