タイトルリンク:CF1245F。ダニエルと春の大掃除
質問の意味:間隔を与え、間隔内の対数がa ^ b == a + bを満たす数を尋ねます;([a、b]と[b、a]は2つの答えです)
分析:質問の意味によると、a&b == 0の対数を見つけることが知られています。これはビット演算であるため、バイナリのデジタルDPに変換でき、1e9は30桁未満です。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int s1[35],s2[35];
ll dp[35][2][2];
ll dfs(int pos,bool lim1,bool lim2)//是否要取上界
{
if(pos==0) return 1;
if(~dp[pos][lim1][lim2]) return dp[pos][lim1][lim2];
int mx1,mx2;mx1=mx2=1;
if(lim1) mx1=s1[pos];
if(lim2) mx2=s2[pos];
ll res=0;
for(int i=0;i<=mx1;i++) for(int j=0;j<=mx2;j++)
if((i&j)==0) res+=dfs(pos-1,lim1&&i==mx1,lim2&&j==mx2);
return dp[pos][lim1][lim2]=res;
}
ll cal(ll a,ll b)
{
if(a<0 || b<0) return 0;
memset(dp,-1,sizeof(dp));
for(int i=1;i<32;i++) s1[i]=a&1,a>>=1,s2[i]=b&1,b>>=1;
return dfs(31,1,1);
}
ll rua()
{
ll a,b;scanf("%lld%lld",&a,&b);
return cal(b,b)-2*cal(a-1,b)+cal(a-1,a-1);
}
int main()
{
int t;scanf("%d",&t);
while(t--) printf("%lld\n",rua());
return 0;
}