51nod 1407 与与与与

1407 与与与与
题目来源: CodeForces
基准时间限制:1.5 秒 空间限制:131072 KB 分值: 320 难度:7级算法题
有n个整数,问从他们中取出若干个数字相与之后结果是0的有多少组。
答案比较大,输出对于 1,000,000,007 (1e9+7)取模后的结果。
Input
第一行输入一个整数n。(1<=n<=1,000,000).
第二行有n个整数a[0],a[1],a[2],...a[n-1],以空格分开.(0<=a[i]<=1,000,000)
Output
对于每一组数据,输出一个整数。
Input示例
3
2 3 3
4
0 1 2 3
Output示例
0

10

题解:对于我这中蒟蒻来说就是神题,看了一天才真正看明白。对于几个数&等于0,有非常多种情况而且状态不好表示,所以就用总的组合方案数(2^n-1)减去相&!=0的方案数即合法方案数。对于几个数&!=0,那么转化成二进制数来看,也就是说n个数最大能合成2^20-1,2^20约等于1000000。那么就枚举0到2^20-1的所有数,其中必定包含所有的ai和所有ai组合合成的数。对于每一个ai,如果aj&ai!=0,那么ai和aj在二进制状态下一定有一位同时为一,那么需要找出ai的所有位中为1的位,在其他a中那些为也为1的和ai组合一定为1,设f【i】表示和i这个数相&任然等于i的a的方案数,由&的运算法则:同为1 才为一,所以得出f【i】所包含的所有a相&一定!=0,(因为在i的每一个“1”位,那些a一定是1)。所以这f【i】个数组合的所有方案数均不合法。最终统计答案用总方案数-不和法方案数=合法方案数,所以这里又要用到容斥原理,

ans=总方案数(2^n-1)-相&后的二进制中有一个1+相&后二进制中有两个1-相&后二进制中有三个1……=相&后没有1(即为0)

总结:容斥原理的题感觉都很#人,所以要多做题,善于发现各个方案数重复的那部分。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define mod 1000000007
#define N 3000000
using namespace std;
inline int read()
{
    int ra,fh;char rx;
    rx=getchar(),ra=0,fh=1;
    while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
    if(rx=='-')fh=-1,rx=getchar();
    while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
}
int n,x,dp[N],g[N];
long long f[N];
long long ans=0;
int main()
{
	scanf("%d",&n);
	int mx=(1<<20)-1;
	for(int i=1;i<=n;i++)
	{
		x=read();dp[x]++;
	}
	f[0]=1;
	for(int i=1;i<=n;i++) f[i]=(f[i-1]<<1)%mod;
	for(int i=20;i>=1;i--)
	    for(int j=mx;j>=0;j--)
	        if(!(j & (1<<(i-1))))
	             dp[j]+=dp[j|(1<<(i-1))];
	ans=f[n]-1;
	for(int i=1;i <= mx;i++)
	{
		g[i]=g[i>>1]+(1&i);
		if(g[i]&1) ans=(ans-f[dp[i]]+1+mod)%mod;
		else ans=(ans+f[dp[i]]-1+mod)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值