2019牛客暑期多校训练营(第七场)H-Pair 数位dp

题目链接:https://ac.nowcoder.com/acm/contest/887/H

题意:

       给你数字A,B,C,询问你能找到多少对(x,y),使得x->[1,A],y->[1,B],并且x&y>C和x^y

做法:

       由于要求上述两个条件中至少满足一个,在处理上需要去重会有些麻烦,所以我们考虑取反,用A*B-sub,sub是同时满足x&y<=C和x^y>=C的数的个数。

       好像蛮典型的数位dp的,dp[pos][la][lb][and][xor]表示,数字a是否达到上限la,数字b是否达到上限lb,&是否满足条件and,^是否满足条件xor,下面的操作就是正常的数位dp做的了。。根据是否需要达到要求规定范围。但是这里最后要减掉max(0ll,A-C+1)和max(0ll,B-C+1),因为在上述条件下,在x=0,y>=C的对数也会被算入,但是题目要求x最低是1,所以要减掉在B大于等于C时,C到B的那些数,y=0的时候同理。


#include
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
using namespace std;
const int maxn=15;
typedef long long ll;
typedef pair pii;
ll dp[35][2][2][2][2];
ll A,B,C;
ll dfs(int pos,int la,int lb,int And,int Xor){
    if(pos<0) return 1;
    if(dp[pos][la][lb][And][Xor]!=-1) return dp[pos][la][lb][And][Xor];
    ll ret=0;
    int na=1,nb=1,nand=1,nxor=0;
    if(la) na=(A>>pos&1);
    if(lb) nb=(B>>pos&1);
    if(And) nand=(C>>pos&1);
    if(Xor) nxor=(C>>pos&1);
    for(int i=0;i<=na;i++){
        for(int j=0;j<=nb;j++){
            if((i&j)>nand) continue;
            if((i^j)

 

你可能感兴趣的:(dp,模板)