UVALive 5063 Just Sum It

来源:互联网 发布:php应用 编辑:程序博客网 时间:2024/05/20 05:06

题意:
给你1~9这9个数字每个数字的最多选择个数,问他们所有不同的选择排列构造出的整数的整数和。

思路:
用背包和组合数可以很容易得到任意情况的方案数,剩下的是考虑怎么求出每个数字对于答案的贡献。
假设数字ax个,求出含有ax1的所有方案数,再将最后一个a插入。对于每一种方案有长度l,枚举l+1种插法,就可以得到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;}
原创粉丝点击