Problem Description
After eating food from Chernobyl, DRD got a super power: he could clone himself right now! He used this power for several times. He found out that this power was not as perfect as he wanted. For example, some of the cloned objects were tall, while some were short; some of them were fat, and some were thin.
More evidence showed that for two clones A and B, if A was no worse than B in all fields, then B could not survive. More specifically, DRD used a vector v to represent each of his clones. The vector v has n dimensions, representing a clone having N abilities. For the i-th dimension, v[i] is an integer between 0 and T[i], where 0 is the worst and T[i] is the best. For two clones A and B, whose corresponding vectors were p and q, if for 1 <= i <= N, p[i] >= q[i], then B could not survive.
Now, as DRD‘s friend, ATM wants to know how many clones can survive at most.
Input
The first line contains an integer T, denoting the number of the test cases.
For each test case: The first line contains 1 integer N, 1 <= N <= 2000. The second line contains N integers indicating T[1], T[2], ..., T[N]. It guarantees that the sum of T[i] in each test case is no more than 2000 and 1 <= T[i].
Output
For each test case, output an integer representing the answer MOD 10^9 + 7.
题目大意:定义向量x = {x1, x2, ……, xn}, y = {y1, y2, ……, yn},有x ≥ y当且仅当对于任意 i 都有 xi ≥ yi。如果x ≥ y,那么 y 不能存在。先给一个向量T,问所有小于等于T的向量中,最多有多少个向量可以共存。
思路:既然没有人写题解,我来写一下……
首先,所有小于等于T的向量的集合,是一个偏序关系,偏序关系中的一条反链就是题目中的一个解,而最长反链就是题目中要求的最大解
根据Dilworth定理,最长反链 = 最小链覆盖
未完待续
代码(125MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <numeric> 6 #include <functional> 7 using namespace std; 8 typedef long long LL; 9 10 const int MAXN = 2010; 11 const int MOD = 1e9 + 7; 12 13 void update_add(int &a, int b) { 14 a += b; 15 if(a >= MOD) a -= MOD; 16 } 17 18 int a[MAXN][MAXN], sum[MAXN][MAXN]; 19 int b[MAXN]; 20 int n, s, T; 21 22 void solve() { 23 memset(a, 0, sizeof(a)); 24 s = accumulate(b, b + n, 0); 25 26 for(int i = 0; i <= b[0]; ++i) a[0][i] = 1; 27 sum[0][0] = a[0][0]; 28 for(int j = 1; j <= s; ++j) sum[0][j] = (sum[0][j - 1] + a[0][j]) % MOD; 29 30 for(int i = 1; i < n; ++i) { 31 for(int j = 0; j <= s; ++j) { 32 //for(int k = j - b[i]; k <= j; ++k) a[i][j] += a[i - 1][k]; 33 if(j - b[i] <= 0) a[i][j] = sum[i - 1][j]; 34 else a[i][j] = (sum[i - 1][j] - sum[i - 1][j - b[i] - 1] + MOD) % MOD; 35 } 36 sum[i][0] = a[i][0]; 37 for(int j = 1; j <= s; ++j) sum[i][j] = (sum[i][j - 1] + a[i][j]) % MOD; 38 } 39 } 40 41 void print() { 42 for(int j = 0; j <= s; ++j) 43 printf("%4d", j); 44 puts(""); 45 for(int i = 0; i < n; ++i) { 46 for(int j = 0; j <= s; ++j) 47 printf("%4d", a[i][j]); 48 puts(""); 49 } 50 } 51 52 int main() { 53 scanf("%d", &T); 54 while(T--) { 55 scanf("%d", &n); 56 for(int i = 0; i < n; ++i) scanf("%d", &b[i]); 57 sort(b, b + n); 58 solve(); 59 //print(); 60 printf("%d\n", a[n - 1][s / 2]); 61 } 62 }