bitset优化01可行背包

例题传送门:『STA - R3』Aulvwc

先讲bitset用法:

1,基础

下标:5 4 3 2 1 0

数字:0 0 0 0 1 0

bitset<n> s表示一个n位的二进制数,空间复杂度:O(n32),可见其非常优秀

因为其跟二进制有关,所以可以使用&,|,对两个位数相同的bitset执行按位与,或,异或运算。

当然也可以使用<<,>>对其进行左移和右移

==,!=也可以比较两个位数相同的bitset代表的二进制数是否相等

2,特有的

s.count()返回二进制串中1的个数

s.set()s的所有位变成1

s.set(k,v)s[k]s的第k位变为v,其中v01

s.reset()s的第k位变为0

s.reset(k)s的第k位变成0

s.filp()s=∼ss所有位取反

s.filp(k)s[k]=1把第k位取反

01背包,即背包中只有01,一般fi表示i这个数能否取到

正常01背包代码

f[0]=1
for(int i=1;i<=n;i++)
for(int j=m;j>=a[i];j--)
f[j]=max(f[j],f[j-a[i]]);

但是对于每个数只有选和不选的情况下

我们考虑构建bitset<m> s,其中第i位表示i能否取到

那么对于加入的ai我们考虑我们选ai,如果我们选ai,那么代表原来能取到j的数,就能取到j+ai,因为第i位表示i能否取到,所以我们选ai能取到的值域就是s<<=ai,不选ai就是s,所以最终的s就是s=(s|(s<<=ai))

代码:

bitset<m> s;
s.set(0,1);
for(int i=1;i<=n;i++)
s|=(s<<a[i]);

非常快,那么例题就可用这种优化优化到O(qnw),w=max(ai)

上代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=2e3+50,M=3e6+50;
ll q,n,a[N],zh;
bool flag=false;
bitset<M> f,f1;
int main()
{
scanf("%lld",&q);
while(q--)
{
flag=false;
zh=0;
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
zh+=a[i];
}
if(zh%n!=0)
{
puts("No");
continue;
}
zh=zh/n;
for(ll i=1;i<=n;i++)
a[i]-=zh;
for(ll i=1;i<=n;i++)
if(a[i]==0) flag=true;
if(flag)
{
puts("Yes");
continue;
}
f.reset();
f1.reset();
f.set(0,1);
f1.set(0,1);
for(ll i=1;i<=n;i++)
{
if(a[i]<0)
{
a[i]=a[i]*-1;
f=(f|(f<<a[i]));
}
else f1=(f1|(f1<<a[i]));
}
f=(f&f1);
if(f.count()>2) puts("Yes");
else puts("No");
}
return 0;
}

注意代码中f.count()>2因为0和都选一定是都能取到的,假如还有第三种能取到,那么就是Yes,否则为No

posted @   傻阙的缺  阅读(1207)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示