题目链接:
http://poj.org/problem?id=3252
做了牛客多校那个数位 <nobr aria-hidden="true"> dp </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi> d </mi> <mi> p </mi> </math> 之后,哇这种题真是太简单我也能做了T_T
我还是喜欢用 <nobr aria-hidden="true"> map </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi> m </mi> <mi> a </mi> <mi> p </mi> </math> 来当 <nobr aria-hidden="true"> dp </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi> d </mi> <mi> p </mi> </math> ,不想去弄个偏移量
之前RE了几发,是因为这个是存的二进制位,我只开了 <nobr aria-hidden="true"> 20 </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mn> 20 </mn> </math> 。。。
//#include"bits/stdc++.h"
#include"iostream"
#include"map"
using namespace std;
typedef long long LL;
int a[100];
map<int,LL>dp[100][3];
LL dfs(int pos,int pre,int sum,bool lim)
{
if(pos==-1)
{
if(sum>=0)return 1;
else return 0;
}
if(lim==0&&dp[pos][pre][sum])return dp[pos][pre][sum];
int up=lim?a[pos]:1;
LL cnt=0;
for(int i=0;i<=up;i++)
{
if(pre<=1)cnt+=dfs(pos-1,i,sum+(i==0?1:-1),lim&&i==up);
else //从高位往低位枚举还没出现过1,也就是说全是前导零
{
if(i)cnt+=dfs(pos-1,i,sum-1,lim&&i==up);//终于出现1了
else cnt+=dfs(pos-1,pre,sum,lim&&i==up);//还没出现过1
}
}
if(lim==0)dp[pos][pre][sum]=cnt;
return cnt;
}
LL solve(LL n)
{
int pos=-1;
while(n)
{
a[++pos]=n&1;
n>>=1;
}
return dfs(pos,2,0,true);
}
int main()
{
int L,R;
while(cin>>L>>R)
{
cout<<solve(R)-solve(L-1)<<endl;
}
}