Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
A的范围没给,但是估计最大是100000,用滚动数组优化才行#include <iostream> #include <cstring> #include <algorithm> using namespace::std; const int maxt = 1010; const int maxn = 103; const int mod = 1e6; // 多重集组合数 // dp[i][j]:前i种家族组成元素个数为j的集合, 一共有多少种方案 // dp[i+1][j] = Σ(k=0, min(j,cnt[i]))dp[i][j-k] // = Σ(k=1, min(j,cnt[i]))dp[i][j-k] + dp[i][j] // let k' = k - 1, // = Σ(k'=0, min(j-1, cnt[i]-1))dp[i][j-(k'+1)] + dp[i][j] // = Σ(k=0, min(j-1, cnt[i]-1))dp[i][j-k-1] + dp[i][j] ......(1) // while, // dp[i+1][j-1] = Σ(k=0, min(j-1,cnt[i]))dp[i][j-1-k] // = Σ(k=0, min(j-1,cnt[i]-1))dp[i][j-1-k] + dp[i][j-1-cnt[i]] ......(2) // because (1),(2), // dp[i+1][j] = dp[i+1][j-1] - dp[i][j-1-cnt[i]] + dp[i][j] // 滚动数组优化, // dp[j] = dp[j-1] - last[j-1-cnt[i]] + last[j] int T, A, S, B; // 家族数, 总人数, 集合最小元素数, 集合最大元素数 int cnt[maxt]; // 每个家族的人数 int dp[maxt * maxn]; // dp[i][j]:前i种家族组成元素个数为j的集合, 一共有多少种方案 int last[maxt * maxn]; int solve(void) { memset(last, 0, sizeof(last)); last[0] = 1; int ans = 0; for (int i = 0; i < T; ++i) { // 遍历行 dp[0] = 1; for (int j = 1; j <= B; ++j) { // 遍历列 if (j - 1 - cnt[i] >= 0) { dp[j] = dp[j - 1] + last[j] - last[j - 1 - cnt[i]]; } else { dp[j] = dp[j - 1] + last[j]; } dp[j] %= mod; //printf("(%d, %d): %d\n", i, j, dp[j]); if (i == T - 1 && j >= S) ans = (ans + dp[j]) % mod; } memcpy(last, dp, sizeof(dp)); } return ((ans % mod) + mod) % mod; } int main(void) { while (scanf("%d%d%d%d", &T, &A, &S, &B) != EOF) { memset(cnt, 0, sizeof(cnt)); for (int i = 0; i < A; ++i) { int fam; scanf("%d", &fam); cnt[fam - 1]++; } printf("%d\n", solve()); } return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator