CodeForces-914C 數位DP

CodeForces-914C 數位DP

題意給一個二進制數n,和整型k,求1-n有多少個數到1的步長是k。

這裏的走一步是指, 當前這個數變成二進制位1的個數。比如5->2->1,兩步。

n可以很大,但是步長都不會超過1000,預處理出,有x位1的數到1的步長是多少,準備前1000的情況就夠用了。

但是dp讓我感覺有點不好想,從高位到低位枚舉,碰到第i位是1的時候,固定比 i高的位,假設第i位是0,然後可以枚舉第位的所有二進制情況。(因爲第i位取0,保證了不會超過i)

枚舉可以藉助組合數優化,枚舉1的個數,如果當前個數滿足,就把組合的方案數加入到答案。

最後如果不在循環裏處理當前位置1補回來的話,最後還要加一下。

要判一下0的特例,還有1的特例。(1到1的步長是0,但是二進制只有一個1的其他數,到1 的步長是1)

裏面有一個組合數的模板= =,可能不太好看,不喜歡的話可以自己敲一個。

#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;
}
/*




 * */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章