链接:https://ac.nowcoder.com/acm/contest/887/H
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
分数:我觉得有2500+…
链接:https://ac.nowcoder.com/acm/contest/887/H
来源:牛客网
题目描述
Given three integers A,B ,C . Count the number of pairs <x ,yx\ , yx ,y> (with
1
≤
x
≤
A
1 \leq x \leq A
1≤x≤A and
1
≤
y
≤
B
1 \leq y \leq B
1≤y≤B)
such that at least one of the following is true:
- ( x a n d y ) > C (x\ and\ y) > C (x and y)>C
-
(
x
x
o
r
y
)
<
C
(x\ xor\ y) < C
(x xor y)<C
(“and”, “xor” are bit operators)
输入描述:
The first line of the input gives the number of test cases,
T
(
T
≤
100
)
T\ (T \leq 100)
T (T≤100). test cases follow.
For each test case, the only line contains three integers A , B and C .
1
≤
A
,
B
,
C
≤
1
0
9
1 \leq A,B,C \leq 10^9
1≤A,B,C≤109
输出描述:
For each test case, the only line contains an integer that is the number of pairs satisfying the condition given in the problem statement.
输入
3
3 4 2
4 5 2
7 8 5
输出
5
7
31
题意:
给定三个数字A,B,C,求
x
∈
[
1
,
A
]
x\in[1,A]
x∈[1,A],
y
∈
[
1
,
B
]
y\in[1,B]
y∈[1,B]使得
(
x
a
n
d
y
)
>
C
(x\ and\ y) > C
(x and y)>C或者
(
x
x
o
r
y
)
<
C
(x\ xor\ y) < C
(x xor y)<C
的
(
x
,
y
)
(x,y)
(x,y)的数量。
题解:
我们可以将题目转化一下,变成求原问题的补集
x
∈
[
1
,
A
]
x\in[1,A]
x∈[1,A],
y
∈
[
1
,
B
]
y\in[1,B]
y∈[1,B]使得
(
x
a
n
d
y
)
<
=
C
(x\ and\ y) <= C
(x and y)<=C并且
(
x
x
o
r
y
)
>
=
C
(x\ xor\ y) >= C
(x xor y)>=C的
(
x
,
y
)
(x,y)
(x,y)的数量
用A*B减去答案即可
那么我们就可以按照A,B的二进制位从高位到低位进行dp
f
[
x
]
[
u
p
a
]
[
u
p
b
]
[
b
u
t
a
]
[
b
u
t
b
]
[
t
a
]
[
t
b
]
f[x][upa][upb][buta][butb][ta][tb]
f[x][upa][upb][buta][butb][ta][tb]
表示从低到高位数第x位及其更高的位
upa,upb表示之前的高位中是否都是和A,B的对应位相等。
buta,butb表示之前的高位中是否都是0。
ta,tb表示之前的高位中的所有位是否都保证两两异或和等于C的对应位,两两与的结果都保证等于C的对应位即可。
转移的时候切掉两两异或之后,小于C的和与之后大于C的。
最后记住答案要保证为正整数。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll f[34][2][2][2][2][2][2];
int a[34],b[34],c[34],A,B,C;
void work(int *x,int val){
x[0]=0;
if(val==0)x[++x[0]]=0;
while(val){
x[++x[0]]=(val&1);
val>>=1;
}
}
/**
ta : 当前位及其之前的位是否保证 a_x & b_x == c_x
tx : 当前位及其之前的位是否保证 a_x ^ b_x == c_x
up : 当前位及其之前的位是否限制元素大小上限
but : 当前位及其之前的位是否限制元素大小下限
*/
ll dp(int x,int upa,int upb,int buta,int butb,int ta,int tx){
if(x==0){
return buta==0&&butb==0;
/*
保证合法结果为正整数
*/
}
if(f[x][upa][upb][buta][butb][ta][tx]!=-1)return f[x][upa][upb][buta][butb][ta][tx];
ll sum=0;
int na=a[x],nb=b[x];
if(!upa)na=1;
if(!upb)nb=1;
for(int i=0;i<=na;i++){
for(int j=0;j<=nb;j++){
if(ta&&((i&j)>c[x]))continue;
if(tx&&((i^j)<c[x]))continue;
int nupa=(upa&(i==na)),nupb=(upb&(j==nb));
int nbuta=(buta&(i==0)),nbutb=(butb&(j==0));
int nta=(ta&((i&j)==c[x])),ntx=(tx&((i^j)==c[x]));
sum+=dp(x-1,nupa,nupb,nbuta,nbutb,nta,ntx);
}
}
f[x][upa][upb][buta][butb][ta][tx]=sum;
return sum;
}
int w33ha(){
scanf("%d%d%d",&A,&B,&C);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
work(a,A);
work(b,B);
work(c,C);
memset(f,-1,sizeof(f));
ll all=dp(32,1,1,1,1,1,1);
printf("%lld\n",1LL*A*B-all);
return 0;
}
int main(){
int T;scanf("%d",&T);
while(T--)w33ha();
return 0;
}