hdu 4248排列问题
一看就可以用母函数做,不过好久没练DP了,所以还是用DP做了。用dp[i][j]表示前i种石头排出j个出来的种数,当考虑第i种石头石,枚举其使用的个数即可。WA了好几次,是整数相乘精度的问题,使用long long就过了。
/* * hdu1004/win.cpp * Created on: 2012-7-24 * Author : ben */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> #include <queue> #include <set> #include <map> #include <stack> #include <string> #include <vector> #include <deque> #include <list> #include <functional> #include <numeric> #include <cctype> using namespace std; typedef long long LL; const int MAXN = 105; const int MAXV =10005; const int MOD = 1000000007; int nums[MAXN]; int dp[MAXN][MAXV]; int c[MAXV][MAXN]; void InitCombineNum(){ memset(c, 0, sizeof(c)); for (int i = 0; i < MAXV; i++) { c[i][0] = 1; } c[1][1] = 1; for (int i = 2; i < MAXV; i++) { for (int j = 1; j < MAXN; j++) { if(j == i) { c[i][j] = 1; break; } c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD; } } } int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif int N, V, T = 0; InitCombineNum(); while(scanf("%d", &N) == 1) { V = 0; for(int i = 0; i < N; i++) { scanf("%d", &nums[i]); V += nums[i]; } memset(dp, 0, sizeof(dp)); for(int i = 0; i < N; i++) { dp[i][0] = 1; } for(int j = 0; j <= nums[0]; j++) { dp[0][j] = 1; } for(int i = 1; i < N; i++) { for(int j = 1; j <= V; j++) { LL temp = 0; for(int k = 0; k <= nums[i] && k <= j; k++) { temp += (((LL)dp[i - 1][j - k]) * c[j][k]) % MOD; } dp[i][j] = temp % MOD; } } LL ans = 0; for(int j = 1; j <= V; j++) { ans += dp[N - 1][j]; } printf("Case %d: %d\n", ++T, (int)(ans % MOD)); } return 0; }