hdu6348: 序列计数
鉴于给定的排列是随机的。
那么有一个结论,最长上升子序列是$\sqrt n$级别的。
那么我么就可以DP了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define M 300 4 #define MOD 1000000007 5 int a[100010]; 6 int f[10010][310]; 7 int res[310]; 8 int n; 9 int C[10010]; 10 inline void add(int x, int y) { 11 for(int i = x; i <= n; i += (i & -i)) { 12 C[i] += y; 13 if(C[i] >= MOD) C[i] -= MOD; 14 } 15 } 16 inline int query(int x) { 17 int ret = 0; 18 for(int i = x; i; i -= (i & -i)) { 19 ret += C[i]; 20 if(ret >= MOD) ret -= MOD; 21 } 22 return ret; 23 } 24 int main() { 25 int T; 26 scanf("%d", &T); 27 for(int Ca = 1; Ca <= T; ++ Ca) { 28 scanf("%d", &n); 29 int lim = min(M, n); 30 /*for(int i = 0; i <= n; ++ i) { 31 for(int j = 1; j <= lim; ++ j) { 32 f[i][j] = 0; 33 } 34 }*/ 35 for(int i = 1; i <= lim; ++ i) res[i] = 0; 36 for(int i = 1; i <= n; ++ i) f[i][1] = 1; 37 for(int i = 1; i <= n; ++ i) { 38 scanf("%d", &a[i]); 39 } 40 for(int k = 2; k <= lim; ++ k) { 41 for(int i = 1; i <= n; ++ i) C[i] = 0; 42 for(int i = 1; i <= n; ++ i) { 43 f[i][k] = query(a[i] - 1); 44 add(a[i], f[i][k - 1]); 45 res[k] += f[i][k]; 46 if(res[k] >= MOD) res[k] -= MOD; 47 } 48 } 49 res[1] = n; 50 printf("Case #%d: ", Ca); 51 for(int i = 1; i <= lim; ++ i) { 52 printf("%d", res[i]); 53 if(i != lim || lim != n) { 54 printf(" "); 55 } 56 } 57 for(int i = lim + 1; i <= n; ++ i) { 58 printf("0"); 59 if(i != n) printf(" "); 60 } 61 puts(""); 62 } 63 }