题意:给定 l 和 r,求区间 [ l , r ] 内有多少对 a,b 满足 a | b = a+b ;
分析:若两个数 a 和 b 满足 a | b = a + b ,即它们二进制位上 1 不重复,所以是赤裸裸的数位DP;
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
int a[35],b[35];
ll dp[35][2][2];
ll DP(int pos,int lim1,int lim2)
{
if(pos==-1) return 1;
if(dp[pos][lim1][lim2]>0) return dp[pos][lim1][lim2];
int n = lim1==1?a[pos]:1;
int m = lim2==1?b[pos]:1;
ll sum=0;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
if((i&j)==0)
sum+=DP(pos-1,lim1&&i==n,lim2&&j==m);
return dp[pos][lim1][lim2]=sum;
}
ll solve(ll l,ll r)
{
if(l<0||r<0) return 0;
memset(dp,0,sizeof(dp));
for(ll i=0;i<=32;i++) a[i] = (l>>i)&1 , b[i] = (r>>i)&1 ;
return DP(32,1,1);
}
int main()
{
int q; scanf("%d",&q);
while(q--)
{
ll l,r;
scanf("%lld%lld",&l,&r);
ll ans=solve(r,r)-solve(r,l-1)*2+solve(l-1,l-1); //容斥一下
printf("%lld\n",ans);
}
}