1. 程式人生 > >【貪心】【線性基】bzoj2460 [BeiJing2011]元素

【貪心】【線性基】bzoj2460 [BeiJing2011]元素

long xor break max() () type 貪心 zoj main

題意:讓你求一些數在XOR下的帶權極大無關組。

帶權極大無關組可以用貪心,將這些數按權值從大到小排序之後,依次檢驗其與之前的數是否全都線性無關。可以用線性基來搞。

可以用擬陣嚴格證明,不過也可以腦補一下……

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll d[64],p[64];
int cnt;//簡化線性基的大小
bool Insert(ll val){//嘗試插入線性基,返回是否插入成功
	for(int i=62;i>=0;--i){
		if(val&(1ll<<i)){
			if(!d[i]){
				d[i]=val;
				break;
			}
			val^=d[i];
		}
	}
	return val>0;
}
ll QueryMax(){
	ll res=0;
	for(int i=62;i>=0;--i){
		if((res^d[i])>res){
			res^=d[i];
		}
    }      
	return res;
}
ll QueryMin(){
	for(int i=0;i<=62;++i){
		if(d[i]){
			return d[i];
		}
	}
	return 0;
}
void Rebuild(){//化為簡化線性基
	for(int i=62;i>=0;--i){
		for(int j=i-1;j>=0;--j){
			if(d[i]&(1ll<<j)){
				d[i]^=d[j];
			}
		}
	}
	for(int i=0;i<=60;++i){
		if(d[i]){
			p[cnt++]=d[i];
		}
	}
}
ll Kth(ll K){
	ll res=0;
	if(K>=(1ll<<cnt)){
		return -1ll;
	}
	for(int i=60;i>=0;--i){
		if(K&(1ll<<i)){
			res^=p[i];
		}
	}
	return res;
}
int n;
struct Point{
	ll x,y;
	Point(const ll &x,const ll &y){
		this->x=x;
		this->y=y;
	}
	Point(){}
};
Point a[1005];
bool cmp(const Point &a,const Point &b){
	return a.y>b.y;
}
int main(){
//	freopen("bzoj2460.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%lld%lld",&a[i].x,&a[i].y);
	}
	sort(a+1,a+n+1,cmp);
	ll ans=0;
	for(int i=1;i<=n;++i){
		if(Insert(a[i].x)){
			ans+=a[i].y;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

【貪心】【線性基】bzoj2460 [BeiJing2011]元素