标签:数位dp
题意:给两个数A,B,求二进制表示下,区间[A,B]之前总共有多少个1。
思路:设dp[pos][ cnt ]为当前考虑pos位,之前的数中已经有cnt个1的时候,(pos+1)个数位与之前数位组成的含有1的个数。详见
代码:
/********************************************************* file name: LA6527.cpp author : kereo create time: 2015年02月06日 星期五 15时58分10秒 *********************************************************/ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<set> #include<map> #include<vector> #include<stack> #include<cmath> #include<string> #include<algorithm> using namespace std; typedef long long ll; const int sigma_size=26; const int N=100+50; const int MAXN=100000+50; const int inf=0x3fffffff; const double eps=1e-8; const int mod=100000000+7; #define L(x) (x<<1) #define R(x) (x<<1|1) #define PII pair<int, int> #define mk(x,y) make_pair((x),(y)) ll n,m; int bit[N]; ll dp[N][N]; ll dfs(int pos,int cnt,int flag){ if(pos == -1) return cnt; if(flag && dp[pos][cnt]!=-1) return dp[pos][cnt]; int x=flag ? 1 : bit[pos]; ll ans=0; for(int i=0;i<=x;i++){ ans+=dfs(pos-1,cnt+(i == 1),flag || i<x); } if(flag) dp[pos][cnt]=ans; return ans; } ll solve(ll x){ int len=0; do{ bit[len++]=x%2; x/=2; }while(x); return dfs(len-1,0,0); } int main(){ memset(dp,-1,sizeof(dp)); while(~scanf("%lld%lld",&n,&m)){ printf("%lld\n",solve(m)-solve(n-1)); } return 0; }
标签:数位dp
原文地址:http://blog.csdn.net/u011645923/article/details/43565715