Topic Link: Click to open the link
Idea: DP + combination number. Using D[i][j] to represent the first I color of the stone, has used the number of J method, each enumeration of the first type of stone put how many, assuming that K, then the equivalent of K from the J position, the number of pre-processing combinations will be OK.
See the code for details:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include < string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include < cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue># Define MAX (a) > (b)? ( A):(B) #define MIN (a) < (b) ( A):(B)) using namespace Std;typedef long long ll;typedef long double ld;const ld EPS = 1e-9, PI = 3.14159265358979323846264 33832795;const int mod = 1000000000 + 7;const int INF = 0x3f3f3f3f;//& 0x7fffffffconst int seed = 131;const ll INF64 = ll (1e18); const int MAXN = + 10;int t,n,m,kase = 0,a[maxn];ll d[2][maxn*maxn];ll c[maxn*maxn][maxn];inline void Add (l L &a, ll b) {A + = B; if (a >= mod) A-= mod;} void Init () {for (int i = 0; I <= 10000; i++) {c[i][0] = 1; for (int j = 1; J <= min (i, +); j + +) {C[i][j] = c[i-1][j-1]; Add (C[i][j], C[I-1] [j]); }}}int Main () {init (); while (~SCANF ("%d", &n)) {for (int i = 1; I <= n; i++) scanf ("%d", &a[i]); int u = 1; memset (D[u], 0, sizeof (d[u)); D[u][0] = 1; int maxlen = 0; for (int i = 1; I <= n; i++) {maxlen + = A[i]; memset (D[u^1], 0, sizeof (d[u^1)); for (int j = 0, J <= MaxLen; j + +) {for (int k = 0; k <= a[i]; k++) {if (k > J | | D[u][j-k] = = 0) continue; ll cur = c[j][k] * D[u][j-k]; if (cur >= mod) cur%= mod; Add (D[u^1][j], cur); }} u ^= 1; } ll ans = 0; for (int i = 1; I <= maxlen; i++) {Add (ans, d[u][i]); } printf ("Case%d:%i64d\n", ++kase, ans); } return 0;}
HDU 4248 A Famous Stone Collector (DP + combination number)