2020 ccpc 网络赛 1012 Xor

题意:

 

 


 

数位DP

首先,为了方便表示,我们将 |x-y|<=K转化为 x+K>=y 且 y+K>=x。

此时,我们发现,如果用传统的从高位到低位的数位DP,我们无法处理x+K出现进位之后的情况,因此,我们考虑从低位到高位进行DP。

设F[now][opa][opb][opx][opy][dax][day][opw]为状态数组,

now 表示当前DP到了哪一位

opa 表示 x<=A

opb 表示 y<=B

opx 表示 x+K<=y

opy 表示 y+K<=x

dax 表示 now-1 位时 x+K 是否产生了进位

day 表示 now-1 位时 y+K 是否产生了进位

opw 表示 x^y<=w

之后,我们利用记忆化搜索,每次枚举now这一位上 x y是 0 还是 1 ,然后就可以算出opa等变量在now上的取值。

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 long long F[35][2][2][2][2][2][2][2];
 9 int T,A,B,K,W;
10 long long dfs(int now,int opa,int opb,int opx,int opy,int dax,int day,int opw)
11 {
12     if(F[now][opa][opb][opx][opy][dax][day][opw]!=-1)return F[now][opa][opb][opx][opy][dax][day][opw];
13     if(now==31)
14     {
15         if(opa&&opb&&opb&&(opx||dax)&&(opy||day)&&opw)return F[now][opa][opb][opx][opy][dax][day][opw]=1;
16         return F[now][opa][opb][opx][opy][dax][day][opw]=0;
17     }
18     int daa=(A>>now)&1,dab=(B>>now)&1;
19     int dak=(K>>now)&1,daw=(W>>now)&1;
20     F[now][opa][opb][opx][opy][dax][day][opw]=0;
21     for(int i=0;i<=1;i++)
22     {
23         for(int j=0;j<=1;j++)
24         {
25             int nopa,nopb,nopx,nopy,ndax,nday,nopw;
26             nopa=(opa&&i<=daa)||(!opa&&i<daa);
27             nopb=(opb&&j<=dab)||(!opb&&j<dab);
28             
29             nopx=(opx&&((i+dax+dak)&1)>=j)||(!opx&&((i+dax+dak)&1)>j);
30             ndax=(i+dax+dak)>1;
31             
32             nopy=(opy&&((j+day+dak)&1)>=i)||(!opy&&((j+day+dak)&1)>i);
33             nday=(j+day+dak)>1;
34             
35             nopw=(opw&&(i^j)<=daw)||(!opw&&(i^j)<daw);
36             F[now][opa][opb][opx][opy][dax][day][opw]+=dfs(now+1,nopa,nopb,nopx,nopy,ndax,nday,nopw);
37         }
38     }
39     return F[now][opa][opb][opx][opy][dax][day][opw];
40 }
41 int main()
42 {
43     scanf("%d",&T);
44     while(T--)
45     {
46         scanf("%d%d%d%d",&A,&B,&K,&W);
47         memset(F,-1,sizeof(F));
48         printf("%lld\n",dfs(0,1,1,1,1,0,0,1));
49     }
50     return 0;
51 }
View Code

 

posted @ 2020-09-24 14:13  Hzoi_joker  阅读(358)  评论(1编辑  收藏  举报