注意看清公式里的括号,‘这类东西qaq
定义
f(S)
f
(
S
)
为
S
S
中所有数的AND,为集合S去掉元素a后剩余元素
因为0&x=0,所以若对于集合
S
S
,有,那么只要
|S′|<|S|−1
|
S
′
|
<
|
S
|
−
1
,我们可以不断给
S′
S
′
添加元素至
|S′|=|S|−1
|
S
′
|
=
|
S
|
−
1
,所以一个集合
S
S
是合法当且仅当
我们要统计这个东西
对于第二个括号里的东西容斥一下,得
也即
对这个东西dp
令
fi,j,k
f
i
,
j
,
k
表示dp了前i个数,当前的
f(S)=j
f
(
S
)
=
j
,对于枚举的
S′
S
′
有
⋁a∈S′f(Sa))=k
⋁
a
∈
S
′
f
(
S
a
)
)
=
k
,
(−1)|S′|
(
−
1
)
|
S
′
|
的和
对于当前的
a[i]=x
a
[
i
]
=
x
转移有这几种
1:
S
S
中没有x,
2:
S
S
中有x,枚举的中没有x,
f[i+1][j AND x][k AND x]+=f[i][j][k]
f
[
i
+
1
]
[
j
A
N
D
x
]
[
k
A
N
D
x
]
+
=
f
[
i
]
[
j
]
[
k
]
3:
S
S
中有x,枚举的中有x,
f[i+1][j AND x][j OR (k AND x)]−=f[i][j][k]
f
[
i
+
1
]
[
j
A
N
D
x
]
[
j
O
R
(
k
A
N
D
x
)
]
−
=
f
[
i
]
[
j
]
[
k
]
因为显然有
j⊆k
j
⊆
k
,所以dp的复杂度是
O(n3m)
O
(
n
3
m
)
,m是二进制位数
初始化 f0,2m−1,2m−1=1 f 0 , 2 m − 1 , 2 m − 1 = 1 ,答案是 fn,0,0 f n , 0 , 0
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 1024;
const int mod = 1e9+7;
inline void add(int &a,const int &b){a+=b;if(a>=mod)a-=mod;}
inline void dec(int &a,const int &b){a-=b;if(a<0)a+=mod;}
int n,al=maxn-1;
int a[maxn];
int f[2][maxn][maxn];
int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int now=0; f[now][al][al]=1;
for(int i=1;i<=n;i++)
{
now=!now; int x=a[i];
for(int j=0;j<maxn;j++)
{
int oth=al^j;
for(int kk=oth;;kk=(kk-1)&oth)
{
int k=j|kk;
int &temp=f[!now][j][k];
if(temp)
{
add(f[now][j][k],temp);
add(f[now][j&x][k&x],temp);
dec(f[now][j&x][j|(k&x)],temp);
temp=0;
}
if(!kk) break;
}
}
}
printf("%d\n",f[now][0][0]);
return 0;
}