链接: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
and
)
such that at least one of the following is true:
-
(“and”, “xor” are bit operators)
输入描述:
The first line of the input gives the number of test cases,
. test cases follow.
For each test case, the only line contains three integers A , B and C .
输出描述:
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,求
,
使得
或者
的
的数量。
题解:
我们可以将题目转化一下,变成求原问题的补集
,
使得
并且
的
的数量
用A*B减去答案即可
那么我们就可以按照A,B的二进制位从高位到低位进行dp
表示从低到高位数第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;
}