列表

详情


NC221060. Compute'sKnapsack

描述

有一次 Compute 打比赛的时候拿到了一个超大背包,而这个背包不止大这么简单,它可以把装的物品的体积暂时改变,这就使得他可以装更多的东西。

具体的,Compute获得的背包最大容积为 m 。如果背包里面装了 k 件物品,而这 k 件物品的体积分别为 ,则这 k 件物品的总体积 W 就变成了 。其中 表示按位异或运算。

Compute 很开心地带着这个背包去购物,店内有 n 件不同的商品,商品 i 的体积为 w_i,而购买 i 能带给他 a_i 的满足度。

Compute 现在想要知道自己本次购物所能获得的满足度的和最大为多少。

输入描述

第一行两个整数 n,m ,分别表示店内商品的个数和背包的容积。

第二行有 n 个整数 ,分别表示 n 件物品的体积。

第三行有 n 个整数 ,分别表示 n 件物品能带给 Compute 的满足度。

输出描述

在一行输出一个整数,表示 Compute 能获得的满足度和的最大值。

示例1

输入:

4 3
1 3 4 5
2 5 -3 100

输出:

104

示例2

输入:

1 1000000000
1
-1000000000

输出:

0

示例3

输入:

4 8
1 2 4 8
13 6 32 50

输出:

51

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 202ms, 内存消耗: 46604K, 提交时间: 2022-05-03 18:07:58

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=40,M=1e7+5,inf=1e18;
int n,m,w[N],a[N];
struct trie
{
	int ch[M][2],bo[M],tot=0;
	trie(){bo[0]=-inf,tot=0;}
	void insert(int x,int w)
	{
		int u=0;
		for(int i=35;i>=0;i--)
		{
			int v=(x>>i)&1ll;
			if(!ch[u][v]) ch[u][v]=++tot;
			u=ch[u][v];
			bo[u]=max(bo[u],w);
		}
	}
	int ask(int x)
	{
		int u=0,res=-inf;
		for(int i=35;i>=0;i--)
		{
			int a=(x>>i)&1,b=(m>>i)&1;
			if(b) res=max(res,bo[ch[u][a^b^1]]);
			u=ch[u][a^b];
			if(u==0) break;
			if(i==0) res=max(res,bo[u]);
		}
		return res;
	}
}t;
void binary(int x)
{
	vector<int>a;
	while(x)
	{
		a.push_back(x%2);
		x>>=1;
	}
	reverse(a.begin(), a.end());
	for(auto it:a)
		cerr<<it<<" ";
	cerr<<endl;
}
signed main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++) scanf("%lld",&w[i]);
	for(int i=0;i<n;i++) scanf("%lld",&a[i]);
	n=34;
	int res=0;
	for(int j=0;j<(1<<17);j++)
	{
		int cnt=0,sum=0;
		for(int i=0;i<17;i++ )
		{
			if((1<<i)&j)
			{
				cnt^=w[i];
				sum+=a[i];
			}
		}
		if(cnt<=m) res=max(res,sum);
		t.insert(cnt, sum);
	}
	for(int j=0;j<(1<<17);j++)
	{
		int cnt=0,sum=0;
		for(int i=0;i<17;i++)
		{
			if((1<<i)&j)
			{
				cnt^=w[i+17];
				sum+=a[i+17];
			}
		}
		res=max(res,sum+t.ask(cnt));
	}
	cout<<res<<endl;
	return 0;
}

上一题