2020年11月3日提高组 【校测】luogu U138404 选数字
Description–
有 N N N 个数字,会问 Q Q Q 个问题,对于每个问题要求从中选出 3 3 3 个数字,使得这 3 3 3 个数字的按位或的结果恰好等于 x x x,每次选的 3 3 3 个数字只能在从左往右的第 l l l 个数到第 r r r 个数之间选择,输出符合要求的方案数。
Input–
第一行两个数 N N N 和 Q Q Q 第二行 N N N 个数,按照从左到右的顺序给出桌面上的数字接下来 Q Q Q 行,每行 3 3 3 个数字,分别为 l , r , x l,r,x l,r,x
Output–
Q Q Q 行,每行一个数表示方案数
Sample Input–
10 5
2 4 3 7 6 9 8 7 10 15
1 5 7
2 8 14
3 5 7
1 10 15
6 9 12
Sample Output–
9
1
1
81
0
说明–
样例解释
第一个询问,选择范围为
2
,
4
,
3
,
7
,
6
{2,4,3,7,6}
2,4,3,7,6。除了选
2
,
4
,
6
2,4,6
2,4,6 不行,剩下
9
9
9 种方案均可以
数据范围
对于
20
%
20\%
20% 的数据,
n
,
Q
≤
100
n,Q≤100
n,Q≤100
对于
60
%
60\%
60%的数据,
n
,
Q
≤
10000
n,Q≤10000
n,Q≤10000
对于
100
%
100\%
100%的数据,
1
≤
l
≤
r
≤
n
≤
1
0
5
,
1
≤
Q
≤
1
0
5
,
1
≤
1≤l≤r≤n≤10^5,1≤Q≤10^5,1≤
1≤l≤r≤n≤105,1≤Q≤105,1≤桌面上每个数字
,
x
≤
255
,x≤255
,x≤255
解题思路–
设
F
[
i
,
j
]
F[i,j]
F[i,j] 表示区间
(
1
,
i
)
(1,i)
(1,i) 中有多少个数 或
j
=
j
j=j
j=j。
其中所有
i
i
i 的二进制相差奇数个
b
i
t
bit
bit 的容斥系数为
−
1
-1
−1,偶数个
b
i
t
bit
bit 的为
+
1
+1
+1
代码–
#include <iostream>
#include <cstdio>
using namespace std;
int n, q, l, r, x, a, rc[100005];
long long ans, f[100005][300];
long long cal(long long z)
{
return z * (z - 1) * (z - 2) / 6;
}
int main()
{
scanf("%d%d", &n, &q);
rc[0] = 1, rc[1] = -1;
for (int i = 2; i <= 255; ++i)
rc[i] = rc[i >> 1] * rc[i & 1];
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a);
for (int j = 0; j <= 255; ++j)
if ((a | j) == j)
f[i][j] = f[i - 1][j] + 1;
else f[i][j] = f[i - 1][j];
}
for (int i = 1; i <= q; ++i)
{
scanf("%d%d%d", &l ,&r, &x);
ans = 0;
for (int j = x; j; j = (j - 1) & x)
ans += rc[x] * rc[j] * cal(f[r][j] - f[l - 1][j]);
printf("%lld\n", ans);
}
return 0;
}