• Pair(二进制处理+数位dp)(2019牛客暑期多校训练营(第七场))


    示例:

    输入:

    3
    3 4 2
    4 5 2
    7 8 5

    输出:5 7 31

    题意:存在多少对<x,y>满足x&y>C或x^y<C的条件。(0<x<=A,0<y<=B)

    题解:首先逆向考虑,求有多少对(x,y)满足x&y<=C且x^y>=C,然后用A*B去减它即可。然后就是数位dp模板题(数位dp不懂可先补一下知识再看这题),用dp[pos][ia][ib][iand][ixor]表示到第pos位的个数,ia位表示是否是A的上限,ib表示是否是B的上限,iand表示 与 的上限是否是C,ixor表示 异或 的下限是否是C,(当处理至某一位不为上下限时,即其上下限可随便取值,不懂将solve()中//printf("dp[%d][%d][%d][%d][%d]=%lld ",pos,i,j,i&j,i^j,ans);的斜杠去掉,输入示例看过程)因为该dp表示的值与输入的A,B,C有关,所以每次都要memset置-1。因为dfs存在x或y为0的情况。而x、y最小是1,所以要减掉x或y为0的情况。x为0的个数有max(0,B-C+1),即y>=C;同理,y为0有max(0,A-C+1)种。

    code:

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    LL A,B,C,dp[40][2][2][2][2];
    int t,a[40],b[40],c[40];
    LL solve(int pos,int ia,int ib,int iand,int ixor)
    {
        if(pos<0)return 1;
        if(dp[pos][ia][ib][iand][ixor]!=-1)return dp[pos][ia][ib][iand][ixor];
        int up1=1,up2=1,up3=1,up4=0;
        if(ia)up1=a[pos];//如果ia/ib/iand/ixor为0,即此处无上下限约束
        if(ib)up2=b[pos];
        if(iand)up3=c[pos];
        if(ixor)up4=c[pos];
        LL ans=0;
        for(int i=0;i<=up1;i++){
            for(int j=0;j<=up2;j++){
                if((i&j)>up3)continue;
                if((i^j)<up4)continue;
                ans+=solve(pos-1,ia&&(i==a[pos]),ib&&(j==b[pos]),iand&&((i&j)==c[pos]),ixor&&((i^j)==c[pos]));
                //printf("dp[%d][%d][%d][%d][%d]=%lld
    ",pos,i,j,i&j,i^j,ans);
            }
        }
        return dp[pos][ia][ib][iand][ixor]=ans;
    }
    int main()
    {
        scanf("%d",&t);
        while(t--){
            memset(dp,-1,sizeof(dp));
            scanf("%lld%lld%lld",&A,&B,&C);
            LL tA=A,tB=B,tC=C;
            memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(c,0,sizeof(c));
            int i=0,j=0,k=0;
            while(tA||tB||tC){//处理A,B,C的二进制
                if(tA){a[i++]=tA&1;tA=tA>>1;}
                if(tB){b[j++]=tB&1;tB=tB>>1;}
                if(tC){c[k++]=tC&1;tC=tC>>1;}
            }
            LL summ=solve(30,1,1,1,1)-max(A-C+1,0LL)-max(B-C+1,0LL);
            summ=(A*B)-summ;
            printf("%lld
    ",summ);
        }
        return 0;
    }
  • 相关阅读:
    MongoDB 数组
    MongoDB 内嵌文档
    MongoDB 聚合操作
    MongoDB 文档的删除操作
    MongoDB 文档的更新操作
    MongoDB 文档的查询和插入操作
    MongoDB 安装和可视化工具
    SSIS 容器
    SSISDB2:SSIS工程的操作实例
    Replication:distribution 中一直在运行 waitfor delay @strdelaytime 语句
  • 原文地址:https://www.cnblogs.com/Aamir-Dan/p/11364052.html
Copyright © 2020-2023  润新知