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;
}