You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

53 lines
2.3 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7; //取模
const int N = 1010;
const int M = 1010;
int n; //原序列长度
int m; //目标序列长度
int f[N][M];
int a[N];
// 原题链接 https://www.luogu.com.cn/problem/solution/UVA12983
int main() {
//加快读入
cin.tie(0), ios::sync_with_stdio(false);
//文件输入
freopen("UVA12983.in", "r", stdin);
//文件输出
// freopen("UVA12983.out", "w", stdout);
int T;
//测试数据组数
cin >> T;
for (int Case = 1; Case <= T; Case++) { // while(T--) 由于要输出 Case +数字所以写成for,为了怕占用i,j变量起名为idx
cin >> n >> m; //由n个数字中挑选最终严格上升子序列的个数为m 个
int sum = 0; //结果为累加和,因为最终长度为m,可以从m,m+1,m+2,...,n个数字中选择最终长度为m即可
// DP初始化
memset(f, 0, sizeof(f)); // f[i][j]表示 在前i个数字中选择并且是后一位是i的并且长度是j的 子序列 个数
//个数的初始值
//这个初始值有意思:不管给我几个数字,最终生成的是位的子序列,那么,只有一种可能
for (int i = 1; i <= n; i++) f[i][1] = 1;
for (int i = 1; i <= n; i++) cin >> a[i]; //读入原序列
//开始O(N^3)级的DP
//小的数量在外层循环,大的数量在内层循环,这会影响很大的运算速率
for (int j = 2; j <= m; j++) // 小数在外层循环;j=1的已经根据实际意义给上了初始值1从2开始递推
for (int i = j; i <= n; i++) // 大数在内层循环
for (int k = 1; k < i; k++) // 遍历所有前序可能
if (a[k] < a[i]) // 保证严格递增
f[i][j] = (f[k][j - 1] + f[i][j]) % mod; // 不断累加,不断取模
for (int i = m; i <= n; i++) sum += f[i][m]; //在m确定的情况下每个一个m~n之间的原始长度都包含解
cout << "Case #" << Case << ": " << sum << endl;
}
return 0;
}