CodeForces-914C Digital DP

CodeForces-914C Digital DP

The question intends to give a binary number n and an integer k, how many numbers from 1-n to 1 is k.

The step here means that the current number becomes the number of binary bits 1. For example, 5->2->1, two steps.

n can be very large, but the step length will not exceed 1000. The preprocessed number is 1 to 1. What is the step length from 1 to 1? The first 1000 is enough.

But dp makes me feel a little hard to think about. Enumerate from high to low. When the i-th bit is 1, fix the bit higher than i. Assuming that the i-th bit is 0, then you can enumerate all the binary bits of the bit. Happening. (Because the i-th bit is set to 0, it is guaranteed not to exceed i)

Enumeration can be optimized by the number of combinations, enumerate the number of 1, and if the current number is satisfied, add the number of combinations to the answer.

Finally, if you don’t process the current position 1 in the loop, add it at the end.

We have to judge the special case of 0 and the special case of 1. (The step size from 1 to 1 is 0, but the binary has only one other number, and the step size to 1 is 1)

There is a template for the number of combinations ==, which may not be pretty. If you don't like it, you can type one yourself.

#define _debug(x) cerr<<#x<<" = "<<x<<endl

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int MAXN = 1e3 + 59;
const int MOD = 1e9 + 7;

template<typename _Tp, const int BCSize, const _Tp Mod> //add Mod as parameter;
struct Binomial_Coefficient {
    
    
    _Tp fac[BCSize + 1];
    _Tp inv[BCSize + 1];

    inline Binomial_Coefficient() {
    
        //add Mod as parameter;
        fac[0] = 1;
        for (int i = 1; i <= BCSize; i++)
            fac[i] = fac[i - 1] * i % Mod;

        inv[BCSize] = 52180388;
        // printf inv[BCSize] to get & save it;
        for (int i = BCSize - 1; ~i; i--)
            inv[i] = inv[i + 1] * (i + 1) % Mod;
    }

    inline _Tp operator()(const int &n, const int &m) {
    
    
        return fac[n] * inv[m] % Mod * inv[n - m] % Mod;
    }
};

typedef Binomial_Coefficient<long long, 1000, MOD> zuHeShu;
zuHeShu C = zuHeShu();


int kase, Kase;
char s[MAXN];
ll step[MAXN], bits[MAXN], k;
ll dp[MAXN];
int len;

int main() {
    
    

    ios_base::sync_with_stdio(0);
    cin.tie(0);

    cin >> (s + 1) >> k;

    if (k == 0) {
    
    
        cout << 1 << endl;
        return 0;
    }

    for (int i = 1; i <= 1000; i++) {
    
    
        bits[i] = bits[i >> 1] + (i & 1);
        step[i] = step[bits[i]] + 1;
    }

    step[1] = 1;
    step[0] = MAXN;

    len = strlen(s + 1);
    int cnt1 = 0;
    for (int i = 1; i <= len; ++i) {
    
    
        dp[i] = dp[i - 1];
        if (s[i] == '1') {
    
    
            for (int j = 0; j <= len - i; ++j)
                if (step[cnt1 + j] == k)
                    dp[i] = (dp[i] + C(len - i, j)) % MOD;
            cnt1++;
        }
    }
    if (step[cnt1] == k)
        dp[len] = (dp[len] + 1) % MOD;
    if (k == 1)
        dp[len] = (dp[len] + MOD - 1) % MOD;
    cout << dp[len] << endl;
    return 0;
}
/*




 * */

Guess you like

Origin blog.csdn.net/Tighway/article/details/98227700