题目描述
小H是个善于思考的学生,她正在思考一个有关序列的问题。
她的面前浮现出了一个长度为n的序列{ai},她想找出两个非空的集合S、T。
这两个集合要满足以下的条件:
两个集合中的元素都为整数,且都在 [1, n] 里,即Si,Ti ∈ [1, n]。
对于集合S中任意一个元素x,集合T中任意一个元素y,满足x < y。
对于大小分别为p, q的集合S与T,满足 a[s1] xor a[s2] xor a[s3] … xor a[sp] = a[t1] and a[t2] and a[t3] … and a[tq].
小H想知道一共有多少对这样的集合(S,T),你能帮助她吗?
题目解析
设
f
[
i
]
[
j
]
[
k
=
0
/
1
/
2
]
f[i][j][k=0/1/2]
f[i][j][k=0/1/2]表示枚举到
i
i
i 节点,如果
k
=
1
k = 1
k=1 代表
a
n
d
and
and 值为
j
j
j ,如果
k
=
2
k = 2
k=2 代表
x
o
r
xor
xor 值为
j
j
j,如果
k
=
0
k = 0
k=0 则代表一个元素都没取。
因此转移方程有:
f
[
i
]
[
a
[
i
+
1
]
a
n
d
f[i][a[i+1]and
f[i][a[i+1]and
j
]
[
1
]
=
f
[
i
+
1
]
[
j
]
[
0
]
+
f
[
i
+
1
]
[
j
]
[
1
]
+
f
[
i
+
1
]
[
a
[
i
+
1
]
a
n
d
j][1]=f[i+1][j][0]+f[i+1][j][1]+f[i+1][a[i+1]and
j][1]=f[i+1][j][0]+f[i+1][j][1]+f[i+1][a[i+1]and
j
]
[
1
]
j][1]
j][1]
f
[
i
]
[
a
[
i
+
1
]
x
o
r
f[i][a[i+1]xor
f[i][a[i+1]xor
j
]
[
2
]
=
f
[
i
+
1
]
[
j
]
[
1
]
+
f
[
i
+
1
]
[
j
]
[
2
]
+
f
[
i
+
1
]
[
a
[
i
+
1
]
x
o
r
j][2]=f[i+1][j][1]+f[i+1][j][2]+f[i+1][a[i+1]xor
j][2]=f[i+1][j][1]+f[i+1][j][2]+f[i+1][a[i+1]xor
j
]
[
2
]
j][2]
j][2]
最后
f
[
1
]
[
0
]
[
2
]
f[1][0][2]
f[1][0][2]就是答案
还需要用到滚动数组和高精度压位
代码
#include<bits/stdc++.h>
#define ll long long
#define M 100000000
using namespace std;
int n;
int a[1030];
struct A
{
int len=0,num[40]={};
}f[2][1030][3];
A operator +(A a,A b)
{
A c;
c.len=max(a.len,b.len);
for(int i=1;i<=c.len;i++)
{
c.num[i]+=a.num[i]+b.num[i];
c.num[i+1]=c.num[i]/M;
c.num[i]%=M;
}
if(c.num[c.len+1]>0) c.len++;
return c;
}
int main()
{
cin>>n;
for(int i=n;i;i--) cin>>a[i];
f[0][1023][0].num[1]=f[0][1023][0].len=1;
int x=0;
for(int i=1;i<=n;i++)
{
memcpy(f[x^1],f[x],sizeof(f[x^1]));
for(int j=0;j<=1023;j++)
{
f[x^1][a[i]&j][1]=f[x][j][0]+f[x][j][1]+f[x^1][a[i]&j][1];
f[x^1][a[i]^j][2]=f[x][j][1]+f[x][j][2]+f[x^1][a[i]^j][2];
}
x^=1;
}
if(f[x][0][2].num[1]==0) {printf("0");return 0;}
printf("%d",f[x][0][2].num[f[x][0][2].len]);
for (int i=f[x][0][2].len-1;i>0;i--) printf("%08d",f[x][0][2].num[i]);
}