• 数位dp——牛客多校H


    /*
    x[1,A]
    y[1,B]
    x^y<C 或 x&y>C
    把ABC拆成二进制后按位进行数位dp 
    dp[pos][s1][s2][f1][f2]
    表示从高到低第pos位,条件一状态为s1,条件2状态为s2,x在pos为的限制状态为f1,y在pos的限制状态为f2的方案数
    条件状态s=0|1|2表示前pos位数运算结果<C前pos位数,=C前pos位数,>C前pos位数 
    dp时枚举下一位的所有可能情况,如果当前状态已经确定(满足或不满足),那么下一位取什么都可以,即下一位的条件状态可以直接继承当前位 
    反之当前状态不确定,即前pos位的值和C相等,那么需要通过当前为来进行判断下一位的条件状态
     
    终止条件:pos==30
        s1==2||s2==0,值为1,反之为0  
    
    考虑要减去的情况 
        x=0,y=[1,min(C-1,B)]都可行
        y=0,x=[1,min(C-1,A)]都可行
         x=0,y=0也可行
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 35
    #define ll long long
    ll A,B,C,dp[maxn][3][3][2][2];
    vector<int>v1,v2,v3;
     
    ll dfs(int pos,int S1,int S2,int f1,int f2){
        ll &res=dp[pos][S1][S2][f1][f2];
        if(res!=-1)return res;
        if(pos==30){//边界条件 
            if(S1==2||S2==0)return res=1;
            else return res=0;
        }
        res=0;
        int newS1,newS2,lim1,lim2;
        lim1=f1?v1[pos]:1;//x下一位的上界 
        lim2=f2?v2[pos]:1;//y下一位的上界 
        for(int i=0;i<=lim1;i++)//枚举xy的下一位 
            for(int j=0;j<=lim2;j++){
                int tmp1=i&j,tmp2=i^j;
                if(S1==1){//先处理条件1 
                     if(tmp1==v3[pos])newS1=1;
                     else if(tmp1<v3[pos])newS1=0;
                     else newS1=2;
                }
                else newS1=S1;
                if(S2==1){
                    if(tmp2==v3[pos])newS2=1;
                     else if(tmp2<v3[pos])newS2=0;
                     else newS2=2;
                } 
                else newS2=S2; 
                res=res+dfs(pos+1,newS1,newS2,f1&&(i==lim1),f2&&(j==lim2));
            } 
        return res;
    }
    void calc(ll x,vector<int> & v){ 
        v.clear();
        for(int i=30;i>0;i--){
            v.push_back(x&1);
            x>>=1;
        }
        reverse(v.begin(),v.end());//把数组倒置后就可以正常数位dp了 
    }
    int main(){
        int t;cin>>t;
        while(t--){
            memset(dp,-1,sizeof dp);
            cin>>A>>B>>C;
            calc(A,v1);calc(B,v2);calc(C,v3);
            ll res=dfs(0,1,1,1,1);//进入搜索时的状态
            res-=min(C-1,A)+min(C-1,B)+1;//0取不到,但数位dp时算了 
            cout<<res<<'
    ';
        }
    } 
  • 相关阅读:
    文档数据库 海量文本分析 搜索引擎 NoSql 数据库 NewSql 数据库 图数据库 知识图谱 联想 白盒人工智能
    我发起了 一个 桌面程序 窗体界面 开源项目 WinFormXml
    调幅 是 电子技术, 调频 是 量子技术
    出一道题 : 证明 超外差收音机 的 混频原理
    研究一下 容器 的 原理
    设计 一个 CPU 的 存储管理部件
    我发起了 一个 操作系统 开源项目, 名字待定
    ServerFul 架构
    谈谈 ServerFul 架构
    状态机 控制机 任务机
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11327242.html
Copyright © 2020-2023  润新知