[2019牛客多校训练第7场]Pair

链接: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 1xA and 1 ≤ y ≤ B 1 \leq y \leq B 1yB)
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 (T100). 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 1A,B,C109

输出描述:

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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值