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;
}

浙公网安备 33010602011771号