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

题目链接: 题目链接

题意:如果一个数二进制n有k位1,那么f1[n] = k,如果k有s位二进制1,那么f2[n] = f1[k] = s.  如此往复,直到fx[n] = 1,此时的x就是n的”K值“,现在要求[L,R]内的”K值“为X的数有多少个。(1<=L<=R<=10^18)

解法:首先可以看到10^18最多只有61位左右的数,所以我们只需处理1~61之间每个数有多少个1,即可知道1~61之间每个数”K值“是多少。

然后就将求[L,R]之间的个数变成求[1,R]-[1,L-1],所以我们只需数出对于每个数n,[1,n]之间有多少个数的”K值“为X即可。

对于二进制来说,可以这样搜索出来:

比如<=101001,要满足有k个1的数的个数,那么我们从高位往低位扫,扫到第一个1,那么现在有两种情况:

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

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

所以如此递归的搜索就可得出答案,也可以用DP做。

代码:

#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

 

你可能感兴趣的:(count)