Luo Gu P4570 BZOJ 2460 [BJWC2011] elements

  • Time limit 20000 ms
  • Memory limit 131072 kB
  • Linux OS

Problem-solving ideas

See clear solution to a problem We will follow the ore mana descending order, and then turn the ore into linear base number to determine whether it will offset the magic ore and has been used previously occurred (linear base still a little ignorant ......), if not cancel, you greedy selected on.

On this question proves the correctness of the greedy, I found the following two

  • Matroid (left pit)

  • A little more ordinary proof https://blog.csdn.net/lqybzx/article/details/79416710

    贪心,按照value从大到小排序然后往线性基里插入就可以得到答案
    下面我们来证明(伪)一下
    我们先进行排序,编号为a[1]到a[n],价值为v[1]到v[n]
    首先证明a[1]一定在答案里
    这里用反证
    假设答案为a[k1],a[k2],……,a[km]
    a[1]不在里面说明a[1]可以被一些线性表示
    即a[1]=a[ki1]^a[ki2]^……^ a[kix]
    那么我们可以用a[1]替换右边的另外一个,使得所有的线性无关
    又a[1]的价值大于右边任意一个,因此a[1]必定在答案里
    接下来考虑a[j]
    如果a[j]可以被a[1]到a[j-1]中的数线性表示,那么a[j]肯定不优,不加入答案
    此时即a[j]无法插入到线性基里面
    如果a[j]不能被a[1]到a[j-1]中的数线性表示,即a[j]可以被插入线性基里
    那么如果a[j]不在答案,那么a[j]必定可以被a[1]到a[j-1]与a[j+1]到a[n]中的数线性表示
    其中a[j+1]到a[n]中至少存在一个
    那么我们用a[j]替换这个数,可以使得所有数的异或不为0
    又a[j]的价值一定比a[j+1]到a[n]中的任意一个大
    因此a[j]如果能够插入线性基,就一定会在答案里
    综上我们只需要按照value从大到小排序后依次插入线性基,把能够插入的累加到ans里即可

源代码

#include<stdio.h>
#include<algorithm>
int n;
struct Data{
    long long id, mogic;
    bool operator < (const Data & a)const{
        return mogic>a.mogic;
    }
}data[1010];

long long b[64];

long long ans=0;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&data[i].id,&data[i].mogic);

    std::sort(data+1,data+1+n);//降序
    for(int i=1;i<=n;i++)
    {
        for(int j=63;j>=0;j--)
        {
            if(!(data[i].id>>j)) continue;
            if(!b[j]) {b[j]=data[i].id;break;}
            else data[i].id^=b[j];
        }
        if(data[i].id) ans+=data[i].mogic;
    }
    printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/wawcac-blog/p/11294501.html