题目大意:

给出一个长度为n的序列,构造出一个序列使得它们的位与和为0,求方案数

也就是从序列里面选出一个非空子集使这些数按位与起来为0.

看了好久才明白题解在干嘛,我们先要表示出两两组合位与和为0的所有情况

先hx一下每个数出现的次数,然后我们从遍历 i ,i 是二进制的数位

然后遍历所有的情况,如果第 i 位有1,那么说明我们去掉第 i 位的1就是又一种情况!

其实我们统计的是所有数在删掉/不删掉每一位的1 所有可能出现的数!

那么,状态内任意组合,不能取空集,把空集加上的话,会发现其实是二项式定理的展开,总数就是

仍然不是很理解,明天再思考思考

 #include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
#define N (1<<20)+100
#define maxn 1000000
#define mod 1000000007
using namespace std; int n;
int hx[N];
ll xx,yy,tt;
ll pw[N],sum[N],ans[];
void get_pw() {pw[]=;for(ll i=;i<=n+;i++) pw[i]=(pw[i-]*(ll))%mod;} int main()
{
freopen("data.in","r",stdin);
scanf("%d",&n);
int x;
for(int i=;i<=n;i++)
{
scanf("%d",&x);
hx[x]++;
sum[x]=hx[x];
}
for(int j=;j<;j++)
{
for(int s=(<<)-;s>=;s--)
if(s&(<<j)) sum[s^(<<j)]+=sum[s];
}
get_pw();
for(int s=;s<(<<);s++)
{
int cnt=;
for(int j=;j<;j++)
if(s&(<<j))
cnt++;
ans[cnt]+=((pw[sum[s]]-)%mod+mod)%mod;
ans[cnt]%=mod;
}
ll ret=;
for(int i=;i<;i++)
{
if(i&) ret-=ans[i],ret%=mod;
else ret+=ans[i],ret%=mod;
}
printf("%lld\n",(ret%mod+mod)%mod);
return ;
}

最新文章

  1. 慎用 supportedRuntime
  2. 初识Windows程序
  3. 11、只允许在主目录下上传和下载文件,不允许用putty登录
  4. AssetBundle系列——资源的加载、简易的资源管理器
  5. HDoj-1228-A + B
  6. ubuntu中查找软件的安装位置
  7. 扩展javascript扩展(类,对象,原型)
  8. c#基础知识索引器
  9. Dynamics CRM OData 查询超过50条记录的数据(Retrieving More than 50 records using OData)
  10. 华为有AI,这场转型战有点大
  11. Fiddler抓包【7】_次要功能和第三方插件
  12. undo与redo
  13. git教程: 查看文件状态与修改内容
  14. delphi Int64Rec 应用实例
  15. Spring Boot 自定义属性 以及 乱码问题
  16. java 常见的异常大集合
  17. iOS Sprite Kit教程之使用帮助文档以及调试程序
  18. HDU 3938 Portal (离线并查集,此题思路很强!!!,得到所谓的距离很巧妙)
  19. 注解@RequestParam——取请求参数
  20. QStackedWidget 与 QStackedLayout 的用法区别

热门文章

  1. Codeforces 787B Not Afraid( 水 )
  2. alsa文章
  3. Spring学习总结(19)——Spring概念详解
  4. CSS BFC学习笔记
  5. 数论(同余+hash)
  6. 怎样在Java中运行Hive命令或HiveQL
  7. html5的postmessage实现js前端跨域訪问及调用解决方式
  8. 51nod-1462: 树据结构
  9. vi 调到第一行,或最后一行
  10. elasticsearch如何安全重启节点