# UVALive 4864 Bit Counting --记忆化搜索 / 数位DP？

1.此处放1：那么就等于求<=1001时放k-1个1的数的个数

2.此处放0：那么后面就随便放了，为C[5][k]

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;

int Count(ll state) {
int cnt = 0;
while(state) {
if(state & 1LL) cnt++;
state >>= 1;
}
return cnt;
}
int WEI(ll state) {
int cnt = 0;
while(state) {
cnt++;
state >>= 1;
}
return cnt;
}
ll C[100][100];
int in[67];

void init()
{
C[0][0] = 1;
for(int i = 1; i < 90; i++) {
C[i][0] = 1;
for(int j = 1; j <= i; j++) {
C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
}
}
memset(in,0,sizeof(in));
in[1] = 0;
for(int i=2;i<=61;i++)
in[i] = in[Count(i)]+1;
}
int X;

ll get(ll state,int cnt) {
if(state < 0) return 0;
int len = WEI(state);
if(len < cnt) return 0;   // not enough
if(cnt == 0)  return 1;   // no demand
return get(state-(1LL<<(len-1)),cnt-1) + C[len-1][cnt];
}

ll getsum(ll R,ll L) {
ll ans = 0;
for(int i=1;i<=61;i++)
if(in[i]+1 == X) ans += get(R,i)-get(L-1,i);
return ans;
}

int main()
{
init();
int i,j;
ll L,R;
while(scanf("%lld%lld%d",&L,&R,&X)!=EOF && L+R+X)
{
ll ans = 0;
if(X == 0 && L == 1LL) { puts("1"); continue; }
if(X == 1 && L == 1LL) ans--;  //1's binary code is 1, but 1 is not in (X==1)
ans += getsum(R,L);
cout<<ans<<endl;
}
return 0;
}
View Code

posted @ 2015-01-22 10:32 whatbeg 阅读(...) 评论(...) 编辑 收藏