zoukankan      html  css  js  c++  java
  • Xor 2020CCPC网络赛 数位DP

    Xor 2020CCPC网络赛

    题目大意:

    题解:

    对于 x y 一共有四个限制,其中只有限制3比较难解决。

    对于这种有进位的限制,需要进行仔细的讨论:

    (|x-y|<=k) ,那么 (0<=k+y-x \,\,&&\,\, x+k-y>=0) ,假设此时枚举到第 i+1 位,那么可以推出:

    [bef_i * 2 + k[i]+y[i]-x[i]>=0 \,\,\,(1) ]

    [bef_i*2+x[i]+k[i]-y[i]>=0\,\,\,(2) ]

    以式子(1) 作为例子分析,式子(2) 同理。

    因为 (k[i]+y[i]-x[i]) 范围是 ([-1,2]) ,接下来对 (bef_i) 进行讨论:

    • (bef_i < -1) ,那么 (1) 恒不成立
    • (bef_i = -1) ,那么要与此时的值一起判断才能确定(1) 是否成立
    • (bef_i = 0) ,那么也要进行判断
    • (bef_i>0) ,那么(1) 恒成立

    分析完这个之后,数位dp的定义就可以确定下来了

    [dp[pos][l1<=A][l2<=B][x \,xor\,y<=W][bef1][bef2] ]

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int mod = 1e9+7;
    ll dp[40][2][2][2][3][3];
    int a[40],b[40],k[40],w[40];
    ll dfs(int pos,int l1,int l2,int sta,int bef1,int bef2){
        if(pos==-1) {
    //        printf("end:pos = %d l1 = %d l2 = %d sta = %d bef1 = %d bef2 = %d
    ",pos,l1,l2,sta,bef1,bef2);
            return bef1>=0&&bef2>=0;
        }
        if(dp[pos][l1][l2][sta][bef1+1][bef2+1]!=-1) return dp[pos][l1][l2][sta][bef1+1][bef2+1];
        int up1 = l1?a[pos]:1,up2 = l2?b[pos]:1;
        int bit1 = k[pos],bit2 = w[pos];
        ll ans = 0;
        for(int i=0;i<=up1;i++){
            for(int j=0;j<=up2;j++){
                if(sta&&(i^j)>bit2) continue;
    //            printf("sec:pos = %d l1 = %d l2 = %d sta = %d bef1 = %d bef2 = %d i = %d j = %d
    ",pos,l1,l2,sta,bef1,bef2,i,j);
                ll x1 = bef1*2+bit1+j-i,x2 = bef2*2+bit1+i-j;
                if(x1<-1||x2<-1) continue;
                ans += dfs(pos-1,l1&&i==up1,l2&&j==up2,sta&&((i^j)==bit2),min(x1,1ll),min(x2,1ll));
            }
        }
        return dp[pos][l1][l2][sta][bef1+1][bef2+1] = ans;
    }
    ll solve(){
        int A,B,K,W,pos = 0;
        scanf("%d%d%d%d",&A,&B,&K,&W);
        memset(dp,-1,sizeof(dp));
        while(A||B||K||W){
            a[pos] = A&1,b[pos] = B&1,k[pos] =K&1,w[pos] = W&1;
            A>>=1,B>>=1,K>>=1,W>>=1;
            pos++;
        }
        return dfs(pos-1,1,1,1,0,0);
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            ll ans = solve();
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    2013软考最新大纲
    安卓的第二堂课
    安卓第一堂课
    VS2010的快捷键;VS2012变化的快捷键
    漂亮的表格样式大全
    ASCII说明和ASCII对照表
    Cookie学习笔记
    JavaScript实现功能全集
    1073-成绩排名
    1071-数字的空洞
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14315614.html
Copyright © 2011-2022 走看看