题目链接:

很容易想到一个dp:AcWing 297. 赤壁之战_树状数组表示长度为AcWing 297. 赤壁之战_#include_02,以AcWing 297. 赤壁之战_动态规划_03结尾的上升子序列的个数
转移的话就是从AcWing 297. 赤壁之战_树状数组_04AcWing 297. 赤壁之战_#include_05枚举一个AcWing 297. 赤壁之战_#include_02表示长度,再从AcWing 297. 赤壁之战_树状数组_04AcWing 297. 赤壁之战_树状数组_08枚举一个AcWing 297. 赤壁之战_动态规划_09,再从AcWing 297. 赤壁之战_树状数组_04AcWing 297. 赤壁之战_#include_11枚举一个AcWing 297. 赤壁之战_#define_12
转移就是如果AcWing 297. 赤壁之战_i++_13,表示AcWing 297. 赤壁之战_#include_02可以接在AcWing 297. 赤壁之战_#define_12后面,那么AcWing 297. 赤壁之战_i++_16
复杂度AcWing 297. 赤壁之战_#define_17,可以过这个AcWing 297. 赤壁之战_动态规划_18
显然不是正解,那么我们需要优化掉一层枚举
对于最后一层从AcWing 297. 赤壁之战_树状数组_04AcWing 297. 赤壁之战_#include_11,其实就是对AcWing 297. 赤壁之战_动态规划_21的一个求和,可以树状数组AcWing 297. 赤壁之战_#include_22
所以说这是一个数据结构优化dp
不是正解:

#include <bits/stdc++.h>
#define

using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
int n, a[A], b[A], f[A][A], T, m;

int main(int argc, char const *argv[]) {
cin >> T;
for (int cas = 1; cas <= T; cas++) {
memset(f, 0, sizeof f);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
sort(b + 1, b + n + 1);
for (int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b + 1;
for (int i = 1; i <= n; i++) f[1][i] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
for (int k = 1; k < j; k++)
if (a[k] < a[j]) f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
int ans = 0;
for (int i = 1; i <= n; i++) ans = (ans + f[m][i]) % mod;
printf("Case #%d: %d\n", cas, ans);
}
}

加了树状数组:

#include <bits/stdc++.h>
#define

using namespace std;
const int mod = 1e9 + 7;
int n, a[A], b[A], f[A][A], T, m, t[A];
int lowbit(int x) {return x & -x;}
void add(int x, int val) {while (x <= n) t[x] = (t[x] + val) % mod, x += lowbit(x);}
int ask(int x, int ans = 0) {
while (x) ans = (ans + t[x]) % mod, x -= lowbit(x);
return ans;
}

int main(int argc, char const *argv[]) {
cin >> T;
for (int cas = 1; cas <= T; cas++) {
memset(f, 0, sizeof f);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
sort(b + 1, b + n + 1);
for (int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b + 1;
for (int i = 1; i <= n; i++) f[1][i] = 1;
for (int i = 1; i <= m; i++) {
memset(t, 0, sizeof t);
if (i == 1) add(1, 1);
for (int j = 1; j <= n; j++) f[i][j] = ask(a[j] - 1), add(a[j], f[i - 1][j]);
}
int ans = 0;
for (int i = 1; i <= n; i++) ans = (ans + f[m][i]) % mod;
printf("Case #%d: %d\n", cas, ans);
}
}