• 2019牛客暑期多校训练营(第七场)H. Pair(数位DP)


    链接:https://ac.nowcoder.com/acm/contest/887/H
    来源:牛客网

    题目描述:

    给定A, B, C, 需要求有多少个pair<x,y> 满足(1<x<=A并且1<y<=B)
    • x & y > C or x ^ y < C
     
    解题思路:假设状态dp【pos】【sta1】【sta2】【lim1】【lim2】为,在二进制下,长度为pos的时候,第一个条件为sta1,第二个条件为sta2,X的限制状态为lim1,Y的限制状态为lim2时的方案数。当sta1或者sta2为0时还不确定是否满足条件,为1时满足条件,为2时不满足条件。最后减去X,或者Y为零时不合法的方案数就好了。
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll dp[34][3][3][3][3];
    int num1[34],num2[34],num3[34];
    int len;
    ll dfs(int pos,int sta1,int sta2,int lim1,int lim2){
    //    cout<<pos<<endl;
        if(pos==-1){
            return (sta1==1||sta2==1);
        }
        if(~dp[pos][sta1][sta2][lim1][lim2])return dp[pos][sta1][sta2][lim1][lim2];
        if(sta1==2&&sta2==2){
            return dp[pos][sta1][sta2][lim1][lim2]=0;
        }
       if(sta1==1||sta2==1){
            ll a=0;
            ll b=0;
            if(lim1){
                for(int i=pos;i>=0;i--){
                    if(num1[i]==1){
                        a+=(1<<i);
                    }
                }
            a++;
            }    else a=pow(2,pos+1);
             if(lim2){
                for(int i=pos;i>=0;i--){
                    if(num2[i]==1){
                        b+=(1<<i);
                    }
                }
                b++;
            }else b=pow(2,pos+1);
            return dp[pos][sta1][sta2][lim1][lim2]=(a)*(b);
        }
        int up1=lim1?num1[pos]:1;
        int up2=lim2?num2[pos]:1;
        ll ans=0;
        for(int i=0;i<=up1;i++){
            for(int j=0;j<=up2;j++){
                int op1=i&j;
                int op2=i^j;
                int st1;
                int st2;
                if(op1>num3[pos])st1=1;
                else if(op1==num3[pos])st1=0;
                else st1=2;
                if(op2<num3[pos])st2=1;
                else if(op2>num3[pos])st2=2;
                else st2=0;
                if(sta1==1)st1=1;
                else if(sta1==2)st1=2;
                if(sta2==1)st2=1;
                else if(sta2==2)st2=2;
                ans+=dfs(pos-1,st1,st2,lim1&&i==up1,lim2&&j==up2);
            }
        }
        dp[pos][sta1][sta2][lim1][lim2]=ans;
        return ans;
    }
    int main(){
        int t;
        int a,b,c;
        scanf("%d",&t);
        while(t--){
            memset(dp,-1,sizeof(dp));
            memset(num1,0,sizeof(num1));
            memset(num2,0,sizeof(num2));
            memset(num3,0,sizeof(num3));
            scanf("%d%d%d",&a,&b,&c);
            int len1,len2,len3;
            len1=len2=len3=0;
            int aa,bb,cc;
            aa=a;
            bb=b;
            cc=c;
            while(a){
                num1[len1++]=a&1;
                a/=2;
            }
            while(b){
                num2[len2++]=b&1;
                b/=2;
            }
            while(c){
                num3[len3++]=c&1;
                c/=2;
            }
            len=max(len1,max(len2,len3));
            ll ans=dfs(len-1,0,0,1,1);
            printf("%lld
    ",ans-min(aa,cc-1)-min(bb,cc-1)-1);
        }
        return 0;
    }
  • 相关阅读:
    C#类型转换
    C#面向对象之多态
    C#面向对象之继承
    C#各种字段类型对比
    C#关键字:static
    C#面向对象之封装
    C#关键字:访问修饰符
    C#类型成员:构造函数
    C#类型成员:方法
    C#类类型
  • 原文地址:https://www.cnblogs.com/Zhi-71/p/11323396.html
Copyright © 2020-2023  润新知