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

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}