POJ 3046 Ant Counting——多重集組合數
阿新 • • 發佈:2019-02-06
定義dp【i】【j】為從前i種物品中選j個物品對應的方案總數
狀態轉移方程為:dp【i】【j】 = ∑dp【i-1】【j-k】(k的範圍是【0,min(j,cnt【i】)】)
優化的話只要寫出dp【i】【j】和dp【i】【j-1】對應的求和展開式就能找到兩者之間的關係,從而去掉一重迴圈
最後用滾動陣列優化一下空間,雖然這題不優化也能過
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int mod = 1e6; int T, A, S, B, a[1005]; int dp[2][100005]; void solve() { dp[0][0] = dp[1][0] = 1; for (int i = 1; i <= T; i++) { for (int j = 1; j <= B; j++) { if (j - 1 >= a[i]) dp[i&1][j] = (dp[i&1][j-1]+dp[(i-1)&1][j]-dp[(i-1)&1][j-1-a[i]]+mod)%mod; else dp[i&1][j] = (dp[i&1][j-1]+dp[(i-1)&1][j])%mod; } } } int main() { while (~scanf("%d %d %d %d", &T, &A, &S, &B)) { memset(a, 0, sizeof(a)); int x; for (int i = 1; i <= A; i++) { scanf("%d", &x); a[x]++; } solve(); int ans = 0; for (int i = S; i <= B; i++) ans = (ans + dp[T&1][i])%mod; printf("%d\n", ans); } return 0; }