选数字
\(【题目描述】\)
有\(N(N \leq 10^5)\)个数排成一行,有\(Q(Q \leq 10^5)\)组询问,每一组询问有三个整数\(l_i,r_i,x_i\),求在区间\([l_i,r_i]\)中任意找3个数按位或等于\(x_i\)的方案数。
\(【样例输入】\)
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
\(【样例输出】\)
9
1
1
81
0
\(【考点】\)
位运算、容斥原理
\(【做法】\)


\(【代码】\)
#include<cstdio>
#include<iomanip>
#define int long long
using namespace std;
const int N=1e5+50;
int a[N],n,q;
int cnt[N][280];
int tot[280];
int Calc(int x){return x*(x-1)*(x-2)/6;}//计算组合数C(x,3)
signed main()
{
scanf("%lld%lld",&n,&q);
int l,r,x;
tot[0]=0,tot[1]=tot[2]=1;
for(int i=3;i<=255;i++) tot[i]=tot[i/2]+(i&1);//如果当前位i为1,则tot[i]+1
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
for(int j=0;j<=255;j++){
if((a[i]|j)==j) cnt[i][j]=cnt[i-1][j]+1;//预处理cnt[i][j]
else cnt[i][j]=cnt[i-1][j];
}
}
for(int i=1;i<=q;i++){
int ans=0;
scanf("%lld%lld%lld",&l,&r,&x);
for(int j=0;j<=255;j++){
int t=j|x,p=1;
if(t!=x) continue;
t=tot[x]-tot[j];//判断j与x相差的位数为偶数还是奇数
if(t&1) p=-1;
ans+=p*Calc(cnt[r][j]-cnt[l-1][j]);
}
printf("%lld\n",ans);
}
return 0;
}

浙公网安备 33010602011771号