2019牛客暑期多校训练营(第七场)Pair(记忆化搜索 异或和与)

原题: https://ac.nowcoder.com/acm/contest/887/H

题意:

给出一个 A , B , C A,B,C A,B,C,求出有多少对 ( x , y ) , x ∈ [ 1 , A ] , y ∈ [ 1 , B ] (x,y),x\in [1,A],y\in [1,B] (x,y),x[1,A],y[1,B],满足 x & y > C x\&y>C x&y>C或者 x ⊕ y < C x\oplus y<C xy<C

解析:

“或者”不太好处理,取反,变为求多少对 ( x , y ) (x,y) (x,y)满足 x & y ≤ C x\&y\leq C x&yC并且 x ⊕ y ≥ C x\oplus y\geq C xyC,在这个基础上分析每一位。

考虑 ( x , y ) (x,y) (x,y)在这一位的取值,下面的表可以说明情况(譬如11在 ⊕ \oplus 下变为0, 0 < 1 0<1 0<1,与 x ⊕ y ≥ C x\oplus y\geq C xyC矛盾)

` 1 0
01 区分 & \& &,不区分 ⊕ \oplus 不区分 & \& &,区分 ⊕ \oplus
00 区分 & \& &,使 ⊕ \oplus 矛盾 不区分 & \& &,不区分 ⊕ \oplus
11 不区分 & \& &,使 ⊕ \oplus 矛盾 使 & \& &矛盾,不区分 ⊕ \oplus

注意,区分之后,之后的怎么样无所谓,但是第一个位置如果矛盾就错了,因为位越高,影响越大。

我们在记忆化搜索的过程中,维护是否已经区分 & \& & ⊕ \oplus ,是否解除 A , B A,B A,B限制,是否有一位1(不能取0)。

运行时加 3 m s 3ms 3ms,复杂度 O ( 2 6 ∗ 32 ) O(2^6*32) O(2632)

代码:

#include
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
const LL inf=(1ll<<40)-1;
LL a,b,c;
 
LL dp[2][2][2][2][40][2][2];
 
LL dfs(bool h1,bool h2,bool up1,bool up2,int p,bool And,bool Xor){
    if(p==-1){
        return h1&&h2;
    }
    if(~dp[h1][h2][up1][up2][p][And][Xor])return dp[h1][h2][up1][up2][p][And][Xor];
    dp[h1][h2][up1][up2][p][And][Xor]=0;
    bool f=0;
    if(c&(1ll<<p))f=1;
    if(f){
        rep(i,0,1){
            rep(j,0,1){
                if(!up1&&i&&!(a&(1ll<<p)))continue;
                if(!up2&&j&&!(b&(1ll<<p)))continue;
                if(!Xor&&i==j)continue;
                bool X[6]={up1,up2,And,Xor,h1,h2};
                if(!up1&&i==0&&(a&(1ll<<p)))X[0]=1;
                if(!up2&&j==0&&(b&(1ll<<p)))X[1]=1;
                if(i==j&&i==0)X[2]=1;
                if(i!=j)X[2]=1;
                if(i)X[4]=1;
                if(j)X[5]=1;
 
                dp[h1][h2][up1][up2][p][And][Xor]+=dfs(X[4],X[5],X[0],X[1],p-1,X[2],X[3]);
            }
        }
    }
    else{
        rep(i,0,1){
            rep(j,0,1){
                if(!up1&&i&&!(a&(1ll<<p)))continue;
                if(!up2&&j&&!(b&(1ll<<p)))continue;
                if(!And&&i==j&&i==1)continue;
                bool X[6]={up1,up2,And,Xor,h1,h2};
                if(!up1&&i==0&&(a&(1ll<<p)))X[0]=1;
                if(!up2&&j==0&&(b&(1ll<<p)))X[1]=1;
                if(i!=j)X[3]=1;
                if(i)X[4]=1;
                if(j)X[5]=1;
 
                dp[h1][h2][up1][up2][p][And][Xor]+=dfs(X[4],X[5],X[0],X[1],p-1,X[2],X[3]);
            }
        }
    }
    return dp[h1][h2][up1][up2][p][And][Xor];
}
 
int main(){
    int t;scanf("%d",&t);
    while(t--){
        memset(dp,-1,sizeof dp);
        scanf("%lld%lld%lld",&a,&b,&c);
        LL ans=dfs(0,0,0,0,32,0,0);
        printf("%lld\n",a*b-ans);
    }
}

你可能感兴趣的:(图论/搜索,DP动态规划)