/* 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<<' '; } }