題意:給你一個二元組(l,r),問在[l,r]內有多少組二元組(a,b)滿足a+b==a^b。(1,2)和(2,1)算兩組。
思路:
1. 很容易想到當且僅當兩數每一位同爲1纔會出問題,也就是說異或是沒有進位的。所以a+b==a^b的條件是a&b==1。
2. cal(a,b)函數爲[0,a]與[0,b]內符合條件的二元組數。那麼求[l,r]區間內的二元組數等價於cal(b,b)-2*cal(a-1,b)+cal(a-1,a-1)。
3. 剩下的就是數位dp了。
代碼:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;++i)
#define for1(i,n) for(int i=1;i<=n;++i)
#define IO ios::sync_with_stdio(false);cin.tie(0)
const int inf = 2e9+5;
const ll INf = 8e18;
int len1,len2;
ll dp[35][2][2];
int a[35],b[35];
ll dfs(int pos,int lim1,int lim2){
if(pos<0) return 1;
if(dp[pos][lim1][lim2]!=-1) return dp[pos][lim1][lim2];
int x = lim1?a[pos] : 1;
int y = lim2?b[pos] : 1;
ll ans = 0;
forn(i,x+1){
forn(j,y+1) if((i&j)==0) ans += dfs(pos-1,lim1?(i==a[pos]):0,lim2?(j==b[pos]):0);
}
dp[pos][lim1][lim2] = ans;
return ans;
}
ll cal(int x,int y){
memset(dp,-1,sizeof(dp));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
forn(i,32){
int z = 1<<i;
if(z&x) a[i] = 1;
if(z&y) b[i] = 1;
}
return dfs(31,1,1);
}
int main(){
IO;cout.precision(10);cout<<fixed;
int t;cin>>t;while(t--){
int l,r;cin>>l>>r;
if(l)cout << cal(r,r)-2*cal(l-1,r)+cal(l-1,l-1) <<'\n';
else cout<<cal(r,r)<<'\n';
}
return 0;
}