版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/82222269
设
表示
的最低
位构成的数。
设
表示
的最高
为构成的数
设
表示在给出的数列
中,满足:
的
的个数。
那么有转移方程:
的第
位为
时:
的第
位为
时:
即为结果,时间复杂度 。
设
表示
二进制中
的数量,由容斥可得:
预处理一下幂,dp出来之后搞一搞就完事了。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<climits>
using namespace std;
//Container--
//
#define clr(a) memset(a,0,sizeof(a))
typedef long long ll;
const ll md=1e9+7;const int up=1e6,sup=(1<<20)-1;int ar[up+10],dp[21][sup+10],ze[sup+10];ll _2[up+10];
void _init(){
int i,j,k,d,t;for(ze[0]=0,i=1;i<=sup;++i)ze[i]=ze[i^(i&-i)]+1;
for(_2[0]=1,i=1;i<=up;++i)_2[i]=_2[i-1]*2%md;
};
bool cl(){
int i,j,k,d,t,n;if(scanf("%d",&n)==-1)return 0;for(i=1;i<=n;scanf("%d",&ar[i++]));
for(clr(dp[0]),i=1;i<=n;++i)dp[0][ar[i]]++;
for(i=1;i<=20;++i)for(j=0;j<=sup;++j){
if(j&(1<<(i-1)))dp[i][j]=dp[i-1][j];
else
dp[i][j]=dp[i-1][j]+dp[i-1][j^(1<<(i-1))];
}
ll rs=_2[n]-1;for(i=1;i<=sup;++i){
if(ze[i]&1)rs=(md-_2[dp[20][i]]+1+rs)%md;
else
rs=(rs+_2[dp[20][i]]-1+md)%md;
}
printf("%lld\n",rs);
};
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
_init();while(cl());
return 0;
};