如果不考虑|x-y|<=m 就是一道经典数位dp题。
我们当然可以直接维护 x-y 的值,最后判断,但这样空间非常大,完全开不下。
所以我们要对这个式子进行一些变化:
|x-y|<=m
y - x >= -m ,x - y <= m
y + m - x >= 0 ; x + m - y >= 0;
由于x,y,m每一位都只能取1,0
所以每一位的取值范围:[-1,2];
而如果上一位的取值大于等于1,或小于等于-2,则后面的值不会影响前面。
若上一位取值为-1,当前位为2,则会抵消上一位的影响。
所以我们只需要维护截至目前为止,前面y + m - x ,x+ m - y 的值即可。
若为1,或-2则认为无法改变。
具体细节见代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
ll dp[66][4][4][2][2];
int da[66],db[66],dn[66],dm[66],na,nb,nn,nm;
ll dfs(int len,int val1,int val2,bool la,bool lb)
{
//cout<< len <<" "<<val1<<" "<<val2<<" "<<la<<" "<<lb<<endl;
val1 = min(val1,1),val2 = min(val2,1);//大于等于1,后面无论取什么都无法改变前面一位的1
if(val1 < -1 || val2 < -1)return 0;
if(len <= 0)return val1 >= 0 && val2 >= 0;
if(~dp[len][val1 + 1][val2 + 1][la][lb])return dp[len][val1 + 1][val2 + 1][la][lb];
ll ans = 0;
int upx = la ? da[len] : 1;
int upy = lb ? db[len] : 1;
for(int i = 0;i <= upx;i++)
for(int j = 0;j <= upy;j++)
{
if(i ^ j == dn[len])
{
int tp1 = i + dm[len] - j;
int tp2 = j + dm[len] - i;
// cout<<"=========== "<<len<<" "<<i <<" - "<<j<<" "<<tp1<<" "<<tp2<<" - - -- "<<dm[len]<<endl;
ans += dfs(len-1,val1 * 2 + tp1,val2 * 2 + tp2,la && i == upx,lb && j == upy);
}
}
dp[len][val1 + 1][val2 + 1][la][lb] = ans;
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T ;
cin>>T;
while(T--)
{
ll a,b,n,m;
cin>>a>>b>>n>>m;
/*
|x-y|<=m
y - x >= -m ,x - y <= m
y + m - x >= 0 ; x + m - y >= 0;
-11, -1, 0, 12
0, 1, 2, 3
*/
//初始化不要忘记
memset(da,0,sizeof(da));
memset(db,0,sizeof(db));
memset(dn,0,sizeof(dn));
memset(dm,0,sizeof(dm));
na=nb=nm=nn=0;
while(a)da[++na]=a%2,a/=2;
while(b)db[++nb]=b%2,b/=2;
while(n)dn[++nn]=n%2,n/=2;
while(m)dm[++nm]=m%2,m/=2;
int mx=max(max(na,nb),max(nn,nm));
memset(dp,-1,sizeof(dp));
cout<<dfs(mx,0,0,true,true)<<endl;;
}
return 0;
}