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 }
原文地址:https://www.cnblogs.com/iamqzh233/p/9478631.html