题意:
给你1~9这9个数字每个数字的最多选择个数,问他们所有不同的选择排列构造出的整数的整数和。
思路:
用背包和组合数可以很容易得到任意情况的方案数,剩下的是考虑怎么求出每个数字对于答案的贡献。
假设数字
a
有
代码:
#include<bits/stdc++.h>
using namespace std;
#define CLR(A, X) memset(A, X, sizeof(A))
typedef long long LL;
const int N = 90;
const LL MOD = 1e9+7;
int num[10];
LL dp[10][N], fac[N], c[N][N];
void init() {
fac[0] = c[0][0] = 1;
for(int i = 1; i < N; i++) fac[i] = fac[i-1]*10%MOD;
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;
}
}
int main() {
init();
int T;
scanf("%d", &T);
while(T--) {
int sum = 0;
LL ans = 0;
for(int i = 1; i <= 9; i++) {
scanf("%d", &num[i]);
sum += num[i];
}
for(int v = 1; v <= 9; v++) if(num[v]) {
num[v]--;
CLR(dp, 0);
dp[0][0] = 1;
for(int k = 1; k <= 9; k++)
for(int i = 0; i <= num[k]; i++)
for(int j = sum; j >= i; j--)
(dp[k][j] += dp[k-1][j-i]*c[j][i]%MOD) %= MOD;
for(int i = 0; i <= sum; i++)
for(int j = 0; j <= i; j++)
(ans += dp[9][i]*v*fac[j]%MOD) %= MOD;
num[v]++;
}
printf("%lld\n", ans);
}
return 0;
}