cf213 B. Numbers(计数dp)

题意:

给定n和 \(a_0\sim a_9\),问位数不超过n且每个数字 \(i\) 的出现次数不小于 \(a_i\) 的整数有多少个

思路:

这题卡了我很久,其实很简单。。。

\(f(i,j)\) 表示考虑了 \(j\sim 9\) 这些数字,组成不超过 \(i\) 位整数的方案数。

\(f(i,9)=1,a_9\le i \le n\)

\(0<j<9,f(i,j)=\sum\limits _{k=a_j}^if(i-k,j+1)C_i^k\)

\(f(i,0)=\sum\limits _{k=a_0}^{i-1} f(i-k,1)C_{i-1}^k\)

注意1e9乘1e9要开long long

const int N = 105, MOD = 1e9 + 7;
ll n, a[10], C[N][N], f[N][10], ans;

main()
{
    cin >> n;
    for(int i = 0; i <= 9; i++) cin >> a[i];

    C[0][0] = 1;
    for(int i = 1; i <= n; i++)
    {
        C[i][0] = 1;
        for(int j = 1; j <= i; j++)
            C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;
    }

    for(int i = a[9]; i <= n; i++) f[i][9] = 1;

    for(int j = 8; j; j--)
        for(int i = a[j]; i <= n; i++)
            for(int k = a[j]; k <= i; k++)
                (f[i][j] += f[i-k][j+1] * C[i][k] % MOD) %= MOD;

    for(int i = a[0]; i <= n; i++)
    {
        for(int k = a[0]; k < i; k++)
            (f[i][0] += f[i-k][1] * C[i-1][k] % MOD) %= MOD;
        (ans += f[i][0]) %= MOD;
    }
    cout << ans;
}

posted @ 2022-03-02 14:40  Bellala  阅读(36)  评论(0)    收藏  举报