对于一个正整数x,我们定义一次操作是将其变为它二进制下“1”的个数,比如我们知道13(10)=1101(2),而1101有三个"1",所以对13进行一次操作就会将其变为3。显而易见的是,对于一个正整数,我们在进行若干次操作后,一定会将其变为1。

给定n和k,其中n是在二进制下被给出,求出所有不大于n且将其变为1的最小操作次数为k的数的个数对10^9+7取模的结果。

因为strlen(str) <= 1000, 使用在预处理1-1000中变化到1时要多少步,中枚举1-1000,然后使用组合数学()

#include <bits/stdc++.h>
#include <iostream>
#include <string.h>

using namespace std;
const int mod = 1e9 + 7;
const int maxn = 1005;
char str[maxn];
int dp[maxn], m;

int getbit(int x) {
    int ans = 0;
    while (x) {ans += x % 2; x /= 2;}
    return ans;
}
int C[maxn][maxn];
void init() {
    for(int i = 0; i <= 1000; ++i)
        C[i][0] = 1;
    for(int i = 1; i <= 1000; ++i) {
        for(int j = 1; j <= 1000; ++j)
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
    }
}

/*
 *
 */
int main() {
//    freopen("in.in", "r", stdin);
    init();
    cin >> str + 1;
    strrev(str + 1);
    int n = strlen(str + 1);
    cin >> m;
    int ans = 0;
    if (m == 0) {cout << "1" << endl; return 0;}
    for(int i = 2; i <= 1000; i++) dp[i] = dp[getbit(i)] + 1;
    for (int i = 1; i <= 1000; i++) {
        if (dp[i] != m - 1) continue;
        int cnt = 0;
        for (int j = n, k = i; j >= 1; j--) {
            if (str[j] == '0') continue;
            if (k == 1) { //这个地方要特别注意一下,因为就剩下最后一个1,所以1-j个位子都可以放1
                ans = (ans + C[j][1]) % mod; break;
            }
            if (j - 1 >= k ) ans = (ans + C[j - 1][k]) % mod; k--;
        }
    }
    if (m == 1) {
        ans = (ans - 1 + mod) % mod;
    }
    cout << ans << endl;
    return 0;
}