题意比较简单吧,就是要你求一对魔法石的集合,并且这些东西都是线性无关的,要是集合的魔力值总和最大
总的来说就是一个线性基模板题。。
我们先将他排序,接着贪心地插入就好了,正确性可以类比于最小生成树,匈牙利等算法,毕竟这也是一个有可以互相推倒性质的东西
有关线性基,我可以感性地认识一下,但你要我十分理性地讲解,估计还不能很好地讲出。。
说一下我学习的时候的当时没有理解好的问题吧吧:
1.线性基中的数不一定是原数的集合中出现过的
2.原数都可以由线性基里的数推出
3.线性基里面的数都可以由原数推出,这个我们可以从他的构造方法得出
同时,这也是线性基的基础
因为要是可以不由原数推出的话,我们直接选择1,10,100,1000,10000就可以解决1,2的问题了
但这显然不是我们想要的
至于怎么得出一个数如何为数集里面得出
我们只需要对线性基的每一位保存一个路径,到时候先用基底弄出这个数,然后将其对应路径输出就可以了。。最好还要去重
这是是我自己yy的,具体我也没有写过。。
有关线性基的板子,可以看这里
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const LL N=1005;
LL n;
struct qq
{LL id,x;
}s[N];
bool cmp (qq a,qq b){return a.x>b.x;}
LL p[65];
bool ins (LL x)
{for (LL u=62;u>=0;u--){if (x>>u&1){if (p[u]==-1) {p[u]=x;return true;} x^=p[u];}}return false;
}
int main()
{memset(p,-1,sizeof(p));scanf("%lld",&n);for (LL u=1;u<=n;u++) scanf("%lld%lld",&s[u].id,&s[u].x);sort(s+1,s+1+n,cmp);LL ans=0;for (LL u=1;u<=n;u++)if (ins(s[u].id)==true)ans=ans+s[u].x;printf("%lld\n",ans);return 0;
}