题目大意:
给定和,求对1e9+7取模的值
其中
思路:
直接枚举计算显然会TLE,考虑用计算二进制每一位对答案的贡献,通过观察可以发现,当时才会对答案有贡献,所以对于i和j,二进制下任意一位都需要满足与的结果不为1,也就是i和j二进制下任意一位都不能同时取1,这也就意味这在二进制运算下并不会产生进位的情况,然后观察,由于不会进位,所以的意义即为的和在二进制下的位数,例如为7(111)时该式的值为3,枚举每一位i和j填的数计算贡献,通过数位dp来统计。
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
const int mod=1e9+7;
int num1[31],num2[31];
vector<int> v;
int dp[35][2][2][2];
int cnt;
int dfs(int pos,int limit1,int limit2,int lead) {
if(pos==0) {
if(lead) return 0;//i+j=0不会产生贡献
return 1;
}
if(dp[pos][limit1][limit2][lead]!=-1) {
return dp[pos][limit1][limit2][lead];
}
int ans=0;
int up1=limit1?num1[pos]:1;
int up2=limit2?num2[pos]:1;
for(int i=0;i<=up1;i++) {
for(int j=0;j<=up2;j++) {
if(i==1&&j==1) continue;//全为1的情况不会产生贡献
int w=-1;
if(lead&&(i||j)) w=pos;//i+j的最高位为pos(之前有前导0的情况下且当前两个数有一个为1)
else w=1;//i+j已经有最高位了
ans=(ans+dfs(pos-1,limit1&&i==up1,limit2&&j==up2,lead&&!i&&!j)*w%mod)%mod;
}
}
return dp[pos][limit1][limit2][lead]=ans;
}
void solve() {
int x,y;
scanf("%lld %lld",&x,&y);
int ans=0;
if(!x&&!y) {
cout<<0<<endl;
return ;
}
cnt=0;
while(x||y) {
num1[++cnt]=x%2;
num2[cnt]=y%2;
x/=2,y/=2;
}
memset(dp,-1,sizeof dp);
printf("%lld\n",dfs(cnt,1,1,1));
}
signed main() {
int T=1;
// ios::sync_with_stdio(false);
// cin.tie(0);
cin>>T;
while(T--) {
solve();
}
}